#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef PACKAGE_NAME
# define PACKAGE_NAME "unice68"
#endif
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION __DATE__
#endif
#ifndef PACKAGE_VERNUM
# define PACKAGE_VERNUM 0
#endif
#include "unice68.h"
#ifdef TYPE_U8
typedef TYPE_U8 u8
#else
typedef unsigned char u8;
#endif
#ifdef TYPE_S8
typedef TYPE_S8 s8
#else
typedef signed char s8;
#endif
#ifdef TYPE_S16
typedef TYPE_S16 s16
#else
typedef signed short s16;
#endif
typedef u8 * areg_t;
typedef int dreg_t;
typedef struct {
areg_t a0,a1,a2,a3,a4,a5,a6,a7;
dreg_t d0,d1,d2,d3,d4,d5,d6,d7;
areg_t ctop,cbot,dtop,dbot;
int overflow;
} all_regs_t;
#define ICE_MAGIC 0x49434521
#define B_CC(CC, LABEL) if (CC) {goto LABEL;} else
#define DB_CC(CC, REG, LABEL) if (!(CC) && --REG >= 0) {goto LABEL;} else
#define DBF(REG,LABEL) DB_CC(0, REG, LABEL)
#define GET_1_BIT_BCC(LABEL) B_CC(!get_1_bit(R), LABEL)
#define DBF_COUNT(REG) ( ( (REG) & 0xFFFF ) + 1 )
static const int direkt_tab[] = {
0x7fff000e,0x00ff0007,0x00070002,0x00030001,0x00030001,
270-1, 15-1, 8-1, 5-1, 2-1
};
static const u8 length_tab[] = {
9,1,0,-1,-1,
8,4,2,1,0
};
static const s8 more_offset[] = {
11, 4, 7, 0,
0x01,0x1f, -1,-1, 0x00,0x1F
};
static const int more_offset_word[] = {
0x0b04,0x0700,0x011f,-1,0x001f
};
#if 0#endif
static void strings(all_regs_t *);
static void normal_bytes(all_regs_t *);
static int get_d0_bits(all_regs_t *, int d0);
static inline int check_drange(all_regs_t *R, const areg_t a, const areg_t b)
{
if (a < R->dtop || b >= R->dbot) {
R->overflow |= 1;
}
return R->overflow;
}
static inline int check_crange(all_regs_t *R, const areg_t a, const areg_t b)
{
if (a < R->ctop || b >= R->cbot) {
R->overflow |= 2;
}
return R->overflow;
}
static inline int getinfo(all_regs_t *R)
{
const areg_t a0 = R->a0;
const int r0 = (0[a0]<<24) + (1[a0]<<16) + (2[a0]<<8) + 3[a0];
R->a0 = a0+4;
return r0;
}
static inline int get_1_bit(all_regs_t *R)
{
int r;
r = (R->d7 & 255) << 1;
B_CC(r & 255, bitfound);
check_crange(R,R->a5-1,R->a5-1);
r = (r>>8) + (*(--R->a5) << 1);
bitfound:
R->d7 = (R->d7 & ~0xFF) | (r & 0xFF);
return r >> 8;
}
static int ice_decrunch(all_regs_t *R)
{
int id;
int csize;
int dsize;
R->ctop = R->a0;
R->dtop = R->a1;
id = getinfo(R);
if (id != ICE_MAGIC) {
return -1;
}
csize = getinfo(R);
R->cbot = R->a5 = R->a0 - 8 + csize;
R->d0 = dsize = getinfo(R);
R->a6 = R->a4 = R->a1;
R->a6 += R->d0;
R->dbot = R->a3 = R->a6;
R->d7 = *(--R->a5);
normal_bytes(R);
R->a6 = R->a3;
GET_1_BIT_BCC(not_packed);
R->d7 = 0x0f9f;
GET_1_BIT_BCC(ice_00);
R->d7 = R->d1 = get_d0_bits(R, 15);
ice_00:
R->d6 = 3;
ice_01:
R->a3 -= 2;
R->d4 = (R->a3[0]<<8) | R->a3[1];
R->d5 = 3;
ice_02:
R->d4 += R->d4;
R->d0 += R->d0 + (R->d4>>16);
R->d4 &= 0xFFFF;
R->d4 += R->d4;
R->d1 += R->d1 + (R->d4>>16);
R->d4 &= 0xFFFF;
R->d4 += R->d4;
R->d2 += R->d2 + (R->d4>>16);
R->d4 &= 0xFFFF;
R->d4 += R->d4;
R->d3 += R->d3 + (R->d4>>16);
R->d4 &= 0xFFFF;
DBF(R->d5,ice_02);
DBF(R->d6,ice_01);
if (check_crange(R, R->a3, R->a3+7)) {
goto not_packed;
}
0[R->a3] = R->d0 >> 8;
1[R->a3] = R->d0;
2[R->a3] = R->d1 >> 8;
3[R->a3] = R->d1;
4[R->a3] = R->d2 >> 8;
5[R->a3] = R->d2;
6[R->a3] = R->d3 >> 8;
7[R->a3] = R->d3;
DBF(R->d7,ice_00);
not_packed:
return -!!R->overflow;
}
static void normal_bytes(all_regs_t *R)
{
while (1) {
const int * tab;
GET_1_BIT_BCC(test_if_end);
R->d1 = 0;
GET_1_BIT_BCC(copy_direkt);
tab = direkt_tab + (20>>2);
R->d3 = 4;
nextgb:
R->d0 = * (--tab);
R->d1 = get_d0_bits(R, R->d0);
R->d0 = (R->d0 >> 16) | ~0xFFFF;
DB_CC((R->d0^R->d1)&0xFFFF, R->d3, nextgb);
R->d1 += tab[(20>>2)];
copy_direkt:
{
const int cnt = DBF_COUNT(R->d1);
if (check_drange(R, R->a6-cnt, R->a6-1) |
check_crange(R, R->a5-cnt, R->a5-1)) {
break;
}
}
lp_copy:
*(--R->a6) = *(--R->a5);
DBF(R->d1,lp_copy);
test_if_end:
if (R->a6 <= R->a4) {
if (R->a6 < R->a4) {
check_drange(R, R->a6, R->a6);
}
break;
}
strings(R);
}
}
static int get_d0_bits(all_regs_t *R, int r0)
{
int r7 = R->d7;
int r1 = 0;
r0 &= 0xFFFF;
if (r0 > 15) {
R->overflow |= 4;
return 0;
}
hole_bit_loop:
r7 = (r7 & 255) << 1;
B_CC(r7 & 255, on_d0);
check_crange(R,R->a5-1,R->a5-1);
r7 = (*(--R->a5) << 1) + (r7>>8);
on_d0:
r1 += r1 + (r7>>8);
DBF(r0,hole_bit_loop);
R->d7 = (R->d7 &~0xFF) | (r7 & 0xFF);
R->d0 |= 0xFFFF;
return r1;
}
static void strings(all_regs_t *R)
{
R->a1 = (areg_t)length_tab;
R->d2 = 3;
get_length_bit:
DB_CC(get_1_bit(R)==0, R->d2, get_length_bit);
R->d4 = R->d1 = 0;
R->d0 = (R->d0 & ~0xFFFF) | (0xFFFF & (s8)R->a1[ 1 + (s16)R->d2 ]);
B_CC(R->d0&0x8000, no_Ober);
R->d1 = get_d0_bits(R, R->d0);
R->d0 |= 0xFFFF;
no_Ober:
R->d4 = R->a1 [ 6 + (s16)R->d2 ];
R->d4 += R->d1;
B_CC(R->d4==0,get_offset_2);
R->a1 = (areg_t)more_offset;
R->d2 = 1;
getoffs:
DB_CC(get_1_bit(R)==0,R->d2,getoffs);
R->d1 = get_d0_bits(R,(int)(s8)more_offset[1+(s16)R->d2]);
R->d0 |= 0xFFFF;
R->d1 += more_offset_word[3+(s16)R->d2];
if (R->d1 < 0) {
R->d1 -= R->d4;
}
goto depack_bytes;
get_offset_2:
R->d1 = 0;
R->d0 = 5;
R->d2 = -1;
GET_1_BIT_BCC(less_40);
R->d0 = 8;
R->d2 = 0x3f;
less_40:
R->d1 = get_d0_bits(R, R->d0);
R->d0 |= 0xFFFF;
R->d1 += R->d2;
depack_bytes:
R->a1 = R->a6 + 2 + (s16)R->d4 + (s16)R->d1;
check_drange(R, R->a6 - DBF_COUNT(R->d4) - 1, R->a6-1);
if (R->a6>R->a4) *(--R->a6) = *(--R->a1);
dep_b:
if (R->a6>R->a4) *(--R->a6) = *(--R->a1);
DBF(R->d4,dep_b);
}
int unice68_get_depacked_size(const void * buffer, int * p_csize)
{
return unice68_depacked_size(buffer,p_csize);
}
int unice68_depacked_size(const void * buffer, int * p_csize)
{
int id, csize, dsize;
int csize_verif = p_csize ? *p_csize : 0;
all_regs_t allregs;
if (csize_verif && csize_verif<12) {
return -1;
}
allregs.a0 = (areg_t)buffer;
id = getinfo(&allregs);
if (id != ICE_MAGIC) {
return -1;
}
csize = getinfo(&allregs);
if (csize < 12) {
return -2;
}
csize -= 12;
dsize = getinfo(&allregs);
if (p_csize) {
*p_csize = csize;
}
if (csize_verif && (csize != csize_verif)) {
dsize = ~dsize;
}
return dsize;
}
int unice68_depacker(void * dest, const void * src)
{
all_regs_t allregs;
allregs.d0 =
allregs.d1 =
allregs.d2 =
allregs.d3 =
allregs.d4 =
allregs.d5 =
allregs.d6 =
allregs.d7 = 0;
allregs.a2 =
allregs.a3 =
allregs.a4 =
allregs.a5 =
allregs.a6 =
allregs.a7 = 0;
allregs.a0 = (areg_t)src;
allregs.a1 = dest;
allregs.overflow = 0;
return ice_decrunch(&allregs);
}
int unice68_ice_version(void)
{
return 240;
}
const char * unice68_versionstr(void)
{
return PACKAGE_NAME " " PACKAGE_VERSION " ICE! 2.40" ;
}
int unice68_version(void)
{
return PACKAGE_VERNUM;
}