home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix Heaven Sunny 2
/
APPARE2.BIN
/
oh_towns
/
dic
/
src
/
comp.c
< prev
next >
Wrap
Text File
|
1995-06-20
|
4KB
|
194 lines
#include "defs.h"
#define NIL (-1)
#define HASH_MAX (1024)
#define HASH_MSK (HASH_MAX - 1)
static short *node = NULL;
static ulong *tab = NULL;
static int hash(char *p)
{
int hs;
hs = *(p++); hs *= 31;
hs += *(p++); hs *= 31;
hs += *(p++);
return (hs & HASH_MSK);
}
static int encode(char *buf, int len, FILE *fp)
{
int i, n, a, b, p;
int cnt, pos, wrt;
char tmp[8 * 2 + 1];
cnt = 0;
pos = 1;
tmp[0] = 0;
b = 0;
wrt = 0;
for ( n = 2048 ; n < (2048 + HASH_MAX) ; n++ )
node[n] = NIL;
while ( b < len ) {
a = 1;
if ( (len - b) >= 3 ) {
for ( i = node[2048 + hash(buf + b)] ; i != NIL ; i = node[i] ) {
if ( buf[i + a] != buf[b + a] )
continue;
for ( n = 0 ; n < 34 && (b + n) < len &&
buf[i + n] == buf[b + n] ; n++ )
;
if ( n > a ) {
a = n;
p = i;
if ( n >= 34 || (b + n) >= len )
break;
}
}
}
if ( a > 2 ) {
n = (p << 5) | (a - 3);
tmp[pos++] = n >> 8;
tmp[pos++] = n & 0xff;
} else {
tmp[0] |= (1 << cnt);
tmp[pos++] = buf[b];
a = 1;
}
if ( a >= 34 || (b + a) >= 2048 ) {
b += a;
} else {
while ( a-- > 0 ) {
n = 2048 + hash(buf + b);
node[b] = node[n];
node[n] = b++;
}
}
if ( ++cnt >= 8 ) {
fwrite(tmp, 1, pos, fp);
wrt += pos;
cnt = 0;
pos = 1;
tmp[0] = 0;
}
}
if ( cnt > 0 ) {
fwrite(tmp, 1, pos, fp);
wrt += pos;
}
return wrt;
}
int compress(int flag, char *file)
{
int i, n, blk;
ulong top, size, pos, block;
ulong skip_size = 0L;
int skip_max = 0;
ulong skip_sta[16];
ulong skip_end[16];
FILE *fp;
uchar *p;
if ( (node = (short *)malloc(sizeof(short) * (2048 + HASH_MAX))) == NULL ||
(tab = (ulong *)malloc(sizeof(ulong) * 256)) == NULL )
return ERR;
#ifdef MSDOS
if ( (fp = fopen(file, "wb")) == NULL )
#else
if ( (fp = fopen(file, "w")) == NULL )
#endif
return ERR;
if ( now_dic_mode == DIC_DEVICE_MODE ) {
size = file_end_block - file_start_block + 1;
} else {
fseek(dev_fp, 0L, 2);
size = ftell(dev_fp);
fseek(dev_fp, 0L, 0);
size = (size + 2047) / 2048;
}
if ( flag ) {
if ( IO_block_read(1) )
return ERR;
i = (dic_buf[0] << 8) | dic_buf[1];
for ( n = 1 ; n <= i ; n++ ) {
p = dic_buf + (n * 16);
if ( (*p & 0xF0) == 0xD0 || *p == 0xE0 ) {
if ( skip_max < 16 ) {
skip_sta[skip_max] = tolong(p + 2);
block = tolong(p + 6);
skip_end[skip_max] = skip_sta[skip_max] + block;
skip_size += block;
skip_max++;
}
}
}
}
fwrite("EDIC", 1, 4, fp);
pos = size * sizeof(long) + 4L;
fseek(fp, pos, 0);
printf("Dictonary Size %ld - %ld = %ld Byte\n",
size * 2048L, skip_size * 2048L, (size - skip_size) * 2048);
printf("compress 0%%\r"); fflush(stdout);
top = 0L;
blk = 0;
for ( block = 1 ; block <= size ; block++ ) {
for ( i = 0 ; i < skip_max ; i++ ) {
if ( block >= skip_sta[i] && block < skip_end[i] )
break;
}
if ( i >= skip_max ) {
if ( IO_block_read(block) )
return ERR;
tab[blk++] = pos;
pos += encode(dic_buf, 2048, fp);
} else {
tab[blk++] = 0L;
}
if ( blk >= 256 ) {
fseek(fp, top * sizeof(long) + 4L, 0);
fwrite(tab, sizeof(long), blk, fp);
fseek(fp, pos, 0);
top += blk;
blk = 0;
printf("compress %3d%%(%3d%%)\r",
(int)(top * 100 / size), (int)((pos / 20L) / top));
fflush(stdout);
}
}
if ( blk > 0 ) {
fseek(fp, top * sizeof(long) + 4L, 0);
fwrite(tab, sizeof(long), blk, fp);
top += blk;
}
printf("compress %3d%%(%3d%%)\n",
(int)(top * 100 / size), (int)((pos / 20L) / top));
fclose(fp);
free(node);
free(tab);
return FALSE;
}