reman3/Rayman_X/cpa/tempgrp/CMP/PC/CMP_DIFF.c

376 lines
10 KiB
C

#include "CMP_Pub.h"
#if defined(D_CMP_DIFF)
#include <stdio.h>
#include "CMP_CPA.h"
#include "ErmCmp.h"
#include "CMP_File.h"
/**************************************************************************/
#define D_CMP_DIFF_CODED
/**************************************************************************/
#define C_CMP_DIFF_BLOCK_FACTOR 1
#define C_CMP_DIFF_BLOCK_SIZE (C_CMP_DIFF_BLOCK_FACTOR<<3)
#define C_CMP_DIFF_NB_BLOCKS 256
/**************************************************************************/
char *CMP_DIFF_g_szCompressionName = "Differential method";
char CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS+1][C_CMP_DIFF_BLOCK_SIZE];
unsigned char CMP_DIFF_g_ucfinish=0;
/**************************************************************************/
/*#define D_CMP_DIFF_CODE_DEBUG*/
#define C_CMP_DIFF_INIT_CODE 0x53
#define C_CMP_DIFF_INIT_CODE1 0xB9
#define C_CMP_DIFF_INIT_CODE2 ((unsigned long) C_CMP_DIFF_INIT_CODE * 0x01010101 + 0x01020304)
unsigned char CMP_DIFF_g_ucCode=C_CMP_DIFF_INIT_CODE;
unsigned char CMP_DIFF_g_ucCheckSum;
long CMP_DIFF_g_lNbCodedBytes=0;
long CMP_DIFF_g_lNbBytes=0;
#if defined(D_CMP_DIFF_CODED)
/**************************************************************************/
unsigned char CMP_DIFF_fn_ucSwapCode(unsigned char code)
{
unsigned char i,newcode=0;
for (i=0;i<8;i++)
{
newcode |= (((code >> i) & 0x1) <<(7-i));
}
return newcode;
}
/**************************************************************************/
unsigned char CMP_DIFF_fn_ucGetCheckSum(FILE *input)
{
unsigned char chksum;
fread(&chksum,sizeof(chksum),1,input);
chksum ^= C_CMP_DIFF_INIT_CODE;
#ifdef D_CMP_DIFF_CODE_DEBUG
printf("get checksum = %d\n",(int) chksum);
#endif
return chksum;
}
/**************************************************************************/
void CMP_DIFF_fn_vSetCheckSum(unsigned char chksum,FILE *output)
{
fseek(output,0L,SEEK_SET);
#ifdef D_CMP_DIFF_CODE_DEBUG
printf("set checksum = %d\n",(int) chksum);
#endif
chksum ^= C_CMP_DIFF_INIT_CODE;
fwrite(&chksum,sizeof(chksum),1,output);
}
/**************************************************************************/
long CMP_DIFF_fn_lGetSize(FILE *input)
{
long size;
fread(&size,sizeof(size),1,input);
size ^= C_CMP_DIFF_INIT_CODE2;
#ifdef D_CMP_DIFF_CODE_DEBUG
printf("get size = %ld\n",(long) size);
#endif
return size;
}
/**************************************************************************/
void CMP_DIFF_fn_vSetSize(long size,FILE *output)
{
#ifdef D_CMP_DIFF_CODE_DEBUG
printf("set size = %ld\n",(long) size);
#endif
size ^= C_CMP_DIFF_INIT_CODE2;
fwrite(&size,sizeof(size),1,output);
}
/**************************************************************************/
long CMP_DIFF_fn_lUncodedGetc(FILE *input)
{
long dummy;
if ((dummy=getc(input))!=EOF) CMP_DIFF_g_lNbBytes++;
return dummy;
}
/**************************************************************************/
long CMP_DIFF_fn_lCodedPutc(int c,FILE *output)
{
long dummy;
dummy = c ^ ((int) ( CMP_DIFF_fn_ucSwapCode(CMP_DIFF_g_ucCode++) ^ C_CMP_DIFF_INIT_CODE1 ));
CMP_DIFF_g_ucCheckSum = (unsigned char)(CMP_DIFF_g_ucCheckSum + (unsigned char)c);
CMP_DIFF_g_lNbCodedBytes++;
dummy = putc(dummy,output);
#ifdef D_CMP_DIFF_CODE_DEBUG
printf("line %04d org %03d coded written %03d checksum %03d\n",(int) CMP_DIFF_g_lNbCodedBytes,(int) c,(int) dummy,(int) CMP_DIFF_g_ucCheckSum);
#endif
return dummy;
}
/**************************************************************************/
long CMP_DIFF_fn_lCodedGetc(FILE *input)
{
int dummy;
int c;
if ((dummy=c=getc(input))!=EOF)
{
dummy = c ^ ((int) ( CMP_DIFF_fn_ucSwapCode(CMP_DIFF_g_ucCode++) ^ C_CMP_DIFF_INIT_CODE1 ));
CMP_DIFF_g_ucCheckSum = (unsigned char)(CMP_DIFF_g_ucCheckSum - (unsigned char)dummy);
CMP_DIFF_g_lNbCodedBytes++;
#ifdef D_CMP_DIFF_CODE_DEBUG
printf("line %04d read %03d decoded fin %03d checksum %03d\n",(int) CMP_DIFF_g_lNbCodedBytes,(int) c,(int) dummy,(int) CMP_DIFF_g_ucCheckSum);
#endif
}
return dummy;
}
/**************************************************************************/
long CMP_DIFF_fn_lUncodedPutc(int c,FILE *output)
{
CMP_DIFF_g_lNbBytes--;
if (CMP_DIFF_g_lNbBytes<0) CMP_DIFF_g_ucfinish=1;
return putc(c,output);
}
/**************************************************************************/
#else /* D_CMP_DIFF_CODED */
/**************************************************************************/
long CMP_DIFF_fn_lUncodedGetc(FILE *input)
{
return getc(input);
}
/**************************************************************************/
long CMP_DIFF_fn_lUncodedPutc(int c,FILE *output)
{
return putc(c,output);
}
/**************************************************************************/
long CMP_DIFF_fn_lCodedGetc(FILE *input)
{
return getc(input);
}
/**************************************************************************/
long CMP_DIFF_fn_lCodedPutc(int c,FILE *output)
{
return putc(c,output);
}
/**************************************************************************/
#endif /* D_CMP_DIFF_CODED */
/**************************************************************************/
void CMP_DIFF_fn_vInitBuffer()
{
int i,j;
for(i=0;i<C_CMP_DIFF_NB_BLOCKS;i++)
{
for (j=0;j<C_CMP_DIFF_BLOCK_SIZE;j++)
{
CMP_DIFF_g_aa_cBuffer[i][j]=(char)i;
}
}
CMP_DIFF_g_lNbCodedBytes=CMP_DIFF_g_lNbBytes=0;
CMP_DIFF_g_ucfinish=0;
CMP_DIFF_g_ucCode=C_CMP_DIFF_INIT_CODE + 4;
}
/**************************************************************************/
void CMP_DIFF_fn_vCompressFile( FILE *input, FILE *output )
{
int i,j,currentsize;
int bestblock = 0;
int bestcount,matchcount;
int changeindex = 0,bitvalue;
CMP_DIFF_fn_vInitBuffer();
#if defined(D_CMP_DIFF_CODED)
CMP_DIFF_fn_vSetCheckSum(CMP_DIFF_g_ucCheckSum=0,output);
CMP_DIFF_fn_vSetSize(CMP_DIFF_g_lNbBytes=0,output);
#endif
while(!CMP_DIFF_g_ucfinish)
{
currentsize=C_CMP_DIFF_BLOCK_SIZE;
for(j=0;j<C_CMP_DIFF_BLOCK_SIZE;j++)
{
i=CMP_DIFF_fn_lUncodedGetc(input);
if (i==EOF)
{
currentsize=j;
break;
}
CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j]=(char)i;
}
if (currentsize==0)
{
CMP_DIFF_g_ucfinish=1;
}
else
{
bestcount=-1;
for(i=0;i<C_CMP_DIFF_NB_BLOCKS;i++)
{
matchcount=0;
for(j=0;j<currentsize;j++)
{
if (CMP_DIFF_g_aa_cBuffer[i][j]==CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j])
{
matchcount++;
}
}
if (matchcount>bestcount)
{
bestcount=matchcount;
bestblock=i;
if (bestcount==currentsize)
break;
}
}
CMP_DIFF_fn_lCodedPutc(bestblock,output);
for (i=0;i<C_CMP_DIFF_BLOCK_FACTOR;i++)
{
changeindex=0;
bitvalue=1;
for (j=i*8;j<i*8+8;j++)
{
if (j>=currentsize)
break;
if (CMP_DIFF_g_aa_cBuffer[bestblock][j] != CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j])
{
changeindex += bitvalue;
}
bitvalue *= 2;
}
CMP_DIFF_fn_lCodedPutc(changeindex,output);
for (j=i*8;j<i*8+8;j++)
{
if (changeindex % 2 == 1)
{
CMP_DIFF_fn_lCodedPutc(CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j],output);
}
changeindex /= 2;
}
if (currentsize<C_CMP_DIFF_BLOCK_SIZE)
{
CMP_DIFF_fn_lCodedPutc(currentsize,output);
CMP_DIFF_g_ucfinish=1;
}
else
{
for(j=0;j<C_CMP_DIFF_BLOCK_SIZE;j++)
{
CMP_DIFF_g_aa_cBuffer[bestblock][j]=CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j];
}
}
}
}
}
#ifdef D_CMP_DIFF_CODED
CMP_DIFF_fn_vSetCheckSum(CMP_DIFF_g_ucCheckSum,output);
CMP_DIFF_fn_vSetSize(CMP_DIFF_g_lNbBytes,output);
#endif
}
/**************************************************************************/
void CMP_DIFF_fn_vExpandFile( FILE *input, FILE *output )
{
int i,j;
int bestblock=-1;
int changeindex = 0;
CMP_DIFF_fn_vInitBuffer();
#ifdef D_CMP_DIFF_CODED
CMP_DIFF_g_ucCheckSum=CMP_DIFF_fn_ucGetCheckSum(input);
CMP_DIFF_g_lNbBytes=CMP_DIFF_fn_lGetSize(input);
#endif
while (!CMP_DIFF_g_ucfinish)
{
if (bestblock==-1)
{
bestblock=CMP_DIFF_fn_lCodedGetc(input);
if (bestblock==EOF)
{
CMP_DIFF_g_ucfinish=1;
}
else
{
changeindex=CMP_DIFF_fn_lCodedGetc(input);
}
}
else
{
bestblock=CMP_DIFF_fn_lCodedGetc(input);
if (bestblock==EOF)
{
for(j=0;j<C_CMP_DIFF_BLOCK_SIZE;j++)
{
CMP_DIFF_fn_lUncodedPutc(CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j],output);
}
CMP_DIFF_g_ucfinish=1;
}
else
{
changeindex=CMP_DIFF_fn_lCodedGetc(input);
if (changeindex==EOF)
{
for(j=0;j<bestblock;j++)
{
CMP_DIFF_fn_lUncodedPutc(CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j],output);
}
CMP_DIFF_g_ucfinish=1;
}
else
{
for(j=0;j<C_CMP_DIFF_BLOCK_SIZE;j++)
{
CMP_DIFF_fn_lUncodedPutc(CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j],output);
}
}
}
}
if (!CMP_DIFF_g_ucfinish)
{
for (i=0;i<C_CMP_DIFF_BLOCK_FACTOR;i++)
{
if (i>0)
changeindex=CMP_DIFF_fn_lCodedGetc(input);
for(j=i*8;j<i*8+8;j++)
{
if (changeindex % 2 == 1)
{
CMP_DIFF_g_aa_cBuffer[bestblock][j]=(char)CMP_DIFF_fn_lCodedGetc(input);
}
CMP_DIFF_g_aa_cBuffer[C_CMP_DIFF_NB_BLOCKS][j]=CMP_DIFF_g_aa_cBuffer[bestblock][j];
changeindex /= 2;
}
}
}
}
#ifdef D_CMP_DIFF_CODED
if (CMP_DIFF_g_lNbBytes==0)
{
if (CMP_DIFF_g_ucCheckSum!=0)
M_CMPFatalError(E_uwCMPCheckSum);
}
else
{
M_CMPFatalError(E_uwCMPFileCorrupted);
}
#endif
}
/**************************************************************************/
#endif /* D_CMP_DIFF */