XADMaster/PPMd/SimpleDecompressor.c
2018-03-21 14:24:50 +02:00

160 lines
4 KiB
C

/*
* SubAllocatorVariantH.c
*
* 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
*/
#include <stdio.h>
#include <stdint.h>
#include "VariantG.h"
#include "VariantH.h"
#include "VariantI.h"
#include "SubAllocatorVariantG.h"
#include "SubAllocatorVariantH.h"
#include "SubAllocatorVariantI.h"
#include "SubAllocatorBrimstone.h"
static inline uint16_t EndianSwap16(uint16_t val) { return (val>>8)|(val<<8); }
static inline uint32_t EndianSwap32(uint32_t val) { return (val>>24)|((val>>8)&0x0000ff00)|((val<<8)&0x00ff0000)|(val<<24); }
static int STDIORead(void *context);
int main(int argc,const char **argv)
{
FILE *fh;
if(argc>=2)
{
fh=fopen(argv[1],"rb");
if(!fh)
{
fprintf(stderr,"Couldn't open file \"%s\".\n",argv[1]);
return 1;
}
}
else fh=stdin;
struct
{
uint32_t magic;
uint32_t attribs;
uint16_t info;
uint16_t namelen;
uint16_t time,date;
} header;
fread(&header,sizeof(header),1,fh);
if(header.magic!=0x84acaf8f&&header.magic!=0x8fafac84)
{
fprintf(stderr,"\"%s\" does not look like a PPMd file.\n",argv[1]);
return 1;
}
if(header.magic==0x8fafac84)
{
header.attribs=EndianSwap32(header.attribs);
header.info=EndianSwap16(header.info);
header.namelen=EndianSwap16(header.namelen);
header.time=EndianSwap16(header.time);
header.date=EndianSwap16(header.date);
}
int maxorder=(header.info&0x0f)+1;
int suballocsize=((header.info>>4)&0xff)+1;
int variant=(header.info>>12)+'A';
int modelrestoration=-1;
if(variant>='I')
{
modelrestoration=header.namelen>>14;
header.namelen&=0x3fff;
}
fprintf(stderr,"PPMd variant %c file.\n",variant);
fprintf(stderr,"Max order = %d\n",maxorder);
fprintf(stderr,"Suballocator size = %d\n",suballocsize);
if(modelrestoration>=0) fprintf(stderr,"Model restoration = %d\n",modelrestoration);
fprintf(stderr,"File attributes = %x\n",header.attribs);
fprintf(stderr,"Time and date = %04x %04x\n",header.time,header.date);
uint8_t namebuf[header.namelen];
fread(namebuf,header.namelen,1,fh);
fprintf(stderr,"Filename = ");
fwrite(namebuf,header.namelen,1,stderr);
fprintf(stderr,"\n");
if(variant!='G'&&variant!='I'&&variant!='H')
{
fprintf(stderr,"Variant %c is not supported.\n",variant);
return 1;
}
switch(variant)
{
case 'G':
{
PPMdSubAllocatorVariantG *alloc=CreateSubAllocatorVariantG(suballocsize<<20);
PPMdModelVariantG model;
StartPPMdModelVariantG(&model,STDIORead,fh,&alloc->core,maxorder,false);
for(;;)
{
int byte=NextPPMdVariantGByte(&model);
if(byte<0) break;
fputc(byte,stdout);
}
}
break;
case 'H':
{
PPMdSubAllocatorVariantH *alloc=CreateSubAllocatorVariantH(suballocsize<<20);
PPMdModelVariantH model;
StartPPMdModelVariantH(&model,STDIORead,fh,alloc,maxorder,false);
for(;;)
{
int byte=NextPPMdVariantHByte(&model);
if(byte<0) break;
fputc(byte,stdout);
}
}
break;
case 'I':
{
PPMdSubAllocatorVariantI *alloc=CreateSubAllocatorVariantI(suballocsize<<20);
PPMdModelVariantI model;
StartPPMdModelVariantI(&model,STDIORead,fh,alloc,maxorder,modelrestoration);
for(;;)
{
int byte=NextPPMdVariantIByte(&model);
if(byte<0) break;
fputc(byte,stdout);
}
}
break;
}
}
static int STDIORead(void *context)
{
FILE *fh=context;
return fgetc(fh)&0xff;
}