diff --git a/lzee.c b/lzee.c new file mode 100644 index 0000000..7b9c2d2 --- /dev/null +++ b/lzee.c @@ -0,0 +1,656 @@ +/* + LZEe - LZE enhancement for z80 by uniabis + + LZE + Copyright (C)1995,2008 GORRY. + + License:original LZE license or zlib/libpng license + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +*/ +/********************************************************************************/ + +#define MACRO +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +/* +cl /O1 /EHs-c- /MD lzee.c +*/ + +void _except_handler4_common() +{ + abort(); +} + +void *memset(void *buf, int ch, size_t n) +{ + unsigned char *ptr = buf; + while (n-- > 0) + { + *(ptr++) = ch; + } + return buf; +} + +void *memcpy(void *buf1, const void *buf2, size_t n) +{ + unsigned char *d = buf1; + const unsigned char *s = buf2; + while (n-- > 0) + { + *(d++) = *(s++); + } + return buf1; +} + +#endif + +#define BZCOMPATIBLE 1 /* 0 or 1 */ +#define SPEED 1 /* 0 or 1 */ +/*int Debug=0;*/ +#define Debug 0 +/* #define DebugMacro(cond,p) if (cond) p */ +#define DebugMacro(cond,p) + +#define N 16384 +#define F 256 + +#if SPEED +#define IDX 8192 +#else +#define IDX 256 +#endif + +FILE *infile; +FILE *outfile; +unsigned long outcount = 0; +unsigned char text[N+F]; +int son[N+1+IDX]; +int dad[N+1+IDX]; +int same[N]; +#define NIL -1 + +/********************************************************************************/ + +void error( char *mes ) +{ + fputs( mes, stderr ); + fputs( "\n", stderr ); + exit(EXIT_FAILURE); +} + +void init_tree( void ) +{ + int i; + + for ( i=0; i99), printf( "Insert Node(%d)\n", r ) ); + + if ( samecount > 0 ) { + same[r] = samecount; + samecount--; + } else { + int i; + unsigned char c; + + p = &text[r]; + c = *(p++); + for ( i=0; i99), printf( "dad[%d]=%d\n", N+1+k, r ) ); + return; + } + son[r] = o; + dad[o] = r; + dad[r] = NIL; + + return; +} + +void delete_node( int p ) +{ + int k, q, r; + + DebugMacro( (Debug>99), printf( "Delete Node(%d)\n", p ) ); +#if SPEED + k = (text[p]<<5) ^ (text[p+1] ); +#else + k = text[p]; +#endif + r = N+1+k; + q = dad[r]; + do { + DebugMacro( (Debug>99), printf( "%d\n", q ) ); + if ( q < 0 ) return; /* if ( q == NIL ) return; */ + if ( p == q ) { + if ( dad[q] < 0 ) { /* if ( dad[q] == NIL ) { */ + son[N+1+k] = son[q]; + } else { + son[dad[q]] = son[q]; + } + dad[r] = dad[q]; + DebugMacro( (Debug>99), printf( "dad[%d]=%d\n", r, dad[q] ) ); + dad[q] = NIL; + return; + } + r = q; + q = dad[q]; + } while (!0); + + return; +} + +int get_node( void ) +{ + int r, o, m, n; + int mlen; + + DebugMacro( (Debug>99), printf( "Get Node\n" ) ); + mlen = 0; + o = nodeo; + r = noder; + if ( o < 0 ) { /* if ( o == NIL ) { */ + return (mlen); + } + + n = same[r]; + do { + unsigned char *p, *q; + int i; + + m = (r-o) & (N-1); + if ( m > 8192 ) return (mlen); + DebugMacro( (Debug>99), printf( "%d ", o ) ); + i = mlen; + p = &text[r+i+1]; + q = &text[o+i+1]; + if ( i ) { i--; if ( *(--p) != *(--q) ) continue; } + if ( i ) { i--; if ( *(--p) != *(--q) ) continue; } + if ( i ) { i--; if ( *(--p) != *(--q) ) continue; } + if ( i ) { i--; if ( *(--p) != *(--q) ) continue; } + i = n; + if ( i > same[o] ) { + i = same[o]; + } + p = &text[r+i]; + q = &text[o+i]; + if ( *(p++) != *(q++) ) continue; + for ( ; iF ) i=F; + DebugMacro( (Debug>99), printf( "%d\n", i ) ); + if ( mlen < i ) { + matchpos = m; + mlen = i; + if ( i >= F ) return (mlen); + } + } while ( (o=son[o]) >= 0 ); /* } while ( (o=son[o]) != NIL ); */ + + return (mlen); +} + +/********************************************************************************/ + +unsigned int flags; +int flagscnt; +int codeptr, code2size; +unsigned char code[256], code2[4]; + +void init_putencode( void ) +{ + code[0] = 0; + codeptr = 1; + flags = 0; + flagscnt = 0; +} + +void sub_putencode( unsigned char c ) +{ + putc( c, outfile ); +} + +int putencode( int r ) +{ + int size; + unsigned int fl; + int fc; + int mlen; + int mpos; + + fl = flags; + fc = flagscnt; + mlen = matchlen; + mpos = matchpos; + size = 0; + if ( mlen < 2 ) { + matchlen = 1; + fl = (fl+fl)+1; + fc += 1; + code2[0] = text[r]; + code2size = 1; + } else { + if (0) { + } else if ( ( mlen < 6 ) && ( mpos < 257 ) ) { +#if 0 + fl = (fl+fl)+0; + fl = (fl+fl)+0; + fl = (fl+fl)+((mlen-2)>>1); + fl = (fl+fl)+((mlen-2)&1); +#else + fl = (fl<<4)+(mlen-2); +#endif + fc += 4; + mpos = 256-mpos; + code2[0] = (unsigned char) (mpos); + code2size = 1; + } else if ( mlen > 9 ) { +#if 0 + fl = (fl+fl)+0; + fl = (fl+fl)+1; +#else + fl = (fl<<2)+1; +#endif + fc += 2; + mpos = 8192-mpos; + code2[0] = (unsigned char) (mpos>>5)&0xf8; + code2[1] = (unsigned char) (mpos & 0xff); + code2[2] = (unsigned char) (mlen-1); + code2size = 3; + } else if ( mlen > 2) { +#if 0 + fl = (fl+fl)+0; + fl = (fl+fl)+1; +#else + fl = (fl<<2)+1; +#endif + fc += 2; + mpos = 8192-mpos; + code2[0] = (unsigned char) ((mpos>>5)&0xf8)|(mlen-2); + code2[1] = (unsigned char) (mpos & 0xff); + code2size = 2; + } else { + matchlen = 1; + fl = (fl+fl)+1; + fc += 1; + code2[0] = text[r]; + code2size = 1; + } + } + if ( fc > 8 ) { + int i; + unsigned char *p; + + fc -= 8; + p = &code[0]; + *(p) = (fl>>fc); + DebugMacro( (Debug), printf( "output code=" ) ); + for ( i=0; i>(8-fc)); + } + DebugMacro( (Debug), printf( "store code($%02X)=", codeptr ) ); + { + unsigned char *p, *q; + int i; + + p = &code[codeptr]; + q = &code2[0]; + for ( i=0; i 8 ) { + flagscnt -= 8; + code[0] = (flags>>flagscnt); + DebugMacro( (Debug), printf( "output code=" ) ); + for ( i=0; i>(8-flagscnt)); + } + DebugMacro( (Debug), printf( "store code($%02X)=", codeptr ) ); + for ( i=0; i 0 ) { + code[0] = (flags<<(8-flagscnt)); + } + if ( codeptr > 1 ) { + DebugMacro( (Debug), printf( "output code=" ) ); + for ( i=0; i len ) matchlen = len; + outcount += putencode( r ); + + DebugMacro( (Debug), printf( "text[r]=$%02X r=%4d s=%4d matchpos=%4d matchlen=%4d\n", text[r], r, s, matchpos, matchlen ) ); + + matchpos = N+1; + mlen = matchlen; + for ( i=0; i printcount ) { + printf( "%12lu\r", incount ); + printcount += 1024*16; + } + while ( i++ < mlen ) { + if ( ok_delete_node ) { + delete_node(s); + } else { + if ( s == N-F-1 ) ok_delete_node = !0; + } + s = (s+1) & (N-1); + r = (r+1) & (N-1); + if ( --len ) { + insert_node(r); + } + } + } while ( len > 0 ); + + NoEncode:; + outcount += finish_putencode(); + printf( "In : %lu bytes\n", incount ); + printf( "Out: %lu bytes\n", outcount ); + if ( incount != 0 ) { + cr = ( 1000 * outcount + (incount/2) ) / incount; + printf( " Out/In: %lu.%03lu\n", cr/1000, cr%1000 ); + } +} + +void decode( unsigned long int size ) +{ + unsigned int flags; + int flagscnt; + int i, j, k, r, c; + unsigned int u; + int bit; + +#define GetBit() \ +{ \ + if ((--flagscnt)<0) { \ + if ((c = getc(infile)) == EOF ) goto Err; \ + DebugMacro( (Debug>99), printf( "\nGetBit($%02X) ", c ) ); \ + flags = c; \ + flagscnt += 8; \ + } \ + bit = ((flags<<=1) & 256 ); \ +} + + r = N-F; +#if BZCOMPATIBLE + if ((c = getc(infile)) == EOF ) goto Err; + putc( c, outfile ); + text[r++] = c; + r &= (N-1); +#endif + flags = 0; + flagscnt = 0; + do { + GetBit(); + if (bit) { + /* 1 */ + if ((c = getc(infile)) == EOF ) break; + DebugMacro( (Debug>99), printf( "1($%02X) ", c ) ); + putc( c, outfile ); + DebugMacro( (Debug), printf( "text[r]=$%02X r=%4d \n", c, r ) ); + text[r++] = c; + r &= (N-1); + } else { + GetBit(); + if (bit) { + /* 01 */ + if ((i = getc(infile)) == EOF ) goto Err; + if ((j = getc(infile)) == EOF ) goto Err; + DebugMacro( (Debug>99), printf( "01($%02X,$%02X) ", i, j ) ); + u = ((i & 0xf8)<<5) | j; + j = i & 0x07; + if ( j == 0 ) { + if ((j = getc(infile)) == EOF ) goto Err; + DebugMacro( (Debug>99), printf( "($%02X) ", j ) ); + if ( j==0 ) goto Quit; + j++; + } else { + j += 2; + } + i = r-(8192-u); + } else { + /* 00 */ + GetBit(); + j = ( bit ? 2 : 0 ); + GetBit(); + j += ( bit ? 1 : 0 ); + j += 2; + if ((i = getc(infile)) == EOF ) goto Err; + DebugMacro( (Debug>99), printf( "00($%02X) ", i ) ); + i = r-(256-i); + } + for ( k=0; k> 24) & 0xff), outfile ); + putc( (int)((size >> 16) & 0xff), outfile ); + putc( (int)((size >> 8) & 0xff), outfile ); + putc( (int)((size >> 0) & 0xff), outfile ); + rewind( infile ); + case 'e': + encode(); + break; + case 'D': + size = (((unsigned long)getc( infile )) << 24); + size |= (((unsigned long)getc( infile )) << 16); + size |= (((unsigned long)getc( infile )) << 8); + size |= (((unsigned long)getc( infile )) << 0); + case 'd': + decode( size ); + break; + } + fclose( infile ); + fclose( outfile ); + printf( "Time: %fs\n", ((double)clock())/CLK_TCK ); + return (EXIT_SUCCESS); +} + + \ No newline at end of file diff --git a/lzee_dec.asm b/lzee_dec.asm new file mode 100644 index 0000000..867815e --- /dev/null +++ b/lzee_dec.asm @@ -0,0 +1,130 @@ +; LZEe DECODE ROUTINE +; +; LZEe - LZE enhancement for z80 by uniabis +; +; LZE Original Copyright (C)1995,2008 GORRY. +; Porting for Z80 by Kei Moroboshi 2017/SEP. +; +; License:original LZE license or zlib/libpng license +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: +; +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software. +; +; 3. This notice may not be removed or altered from any source +; distribution. + + +; .Z80 + +; PUBLIC DECODE_LZEE +;================================================ +;in HL unpack source address +; DE unpack destination address +;================================================ +;work AF,BC,DE,HL,AF',BC',D',HL' +; +;================================================ +DECODE_LZEE: + PUSH HL + LD BC,0 ;CopyCount = 0; + EXX + POP HL + + LD BC,108H ;BitCount=1, BitCountReset=8 +DECODE_LZEE_1: + LD A,(HL) ;*(DECODEPtr++) = *(LZEPtr++); + INC HL + EXX + LD (DE),A ;DE'=DECODEPtr + INC DE + +DECODE_LZEE_lp1: + EXX + + DJNZ SKIP ;if ( (--BitCount) == 0 ) { + LD D,(HL) ; BitData = (int)*(LZEPtr++); + INC HL + LD B,C ; BitCount = 8; } +SKIP: SLA D ;BitData <<= 1; + + JR C,DECODE_LZEE_1 ;jc DECODE_LZEE_1 + + DJNZ SKIP0 ;if ( (--BitCount) == 0 ) { + LD D,(HL) ; BitData = (int)*(LZEPtr++); + INC HL + LD B,C ; BitCount = 8; } +SKIP0: SLA D ;BitData <<= 1; + + JR C,DECODE_LZEE_01 ;jc DECODE_LZEE_01 + + DJNZ SKIP00 ;if ( (--BitCount) == 0 ) { + LD D,(HL) ; BitData = (int)*(LZEPtr++); + INC HL + LD B,C ; BitCount = 8; } +SKIP00: SLA D ;BitData <<= 1; + EXX + RL C + EXX + DJNZ SKIP01 ;if ( (--BitCount) == 0 ) { + LD D,(HL) ; BitData = (int)*(LZEPtr++); + INC HL + LD B,C ; BitCount = 8; } +SKIP01: SLA D ;BitData <<= 1; + LD A,(HL) ;Distance = -256+((int)*(LZEPtr++)); + INC HL + EXX + RL C ;adc CopyCount,CopyCount + LD H,-1 ;Distance=-256+A; + LD L,A +DECODE_LZEE_00_1: + INC C ;inc CopyCount +DECODE_LZEE_00_2: + ADD HL,DE ;HL':CopyPtr=HL:Distance + DE':DECODEPtr + INC BC ;inc CopyCount + LDIR ;copy + JP DECODE_LZEE_lp1 ;[[[ or JR ]]] + +DECODE_LZEE_01: + LD A,(HL) + INC HL + EX AF,AF' + LD A,(HL) + INC HL + EXX + LD L,A + EX AF,AF' + LD C,A + OR 7 + RRCA ;shr DistanceH,1 + RRCA ;shr DistanceH,1 + RRCA ;shr DistanceH,1 + LD H,A + LD A,C + AND 7 + LD C,A + JP NZ,DECODE_LZEE_00_1 ;[[[ or JR ]]] + EXX + LD A,(HL) + INC HL + EXX + LD C,A ;C'=CopyCountL + OR A + JP NZ,DECODE_LZEE_00_2 ;[[[ or JR ]]] + +DECODE_LZEE_e: + RET + + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..b95889c --- /dev/null +++ b/readme.md @@ -0,0 +1,108 @@ +# LZEe - LZE enhancement for z80 by uniabis + + LZE Original Copyright (C)1995,2008 GORRY. + Porting for Z80 by Kei Moroboshi 2017/SEP. + + License:original LZE license or zlib/libpng license + + +## Usage + +``` +lzee.exe E infile outfile + + pack infile to outfile with header + +lzee.exe e infile outfile + + pack infile to outfile without header + +lzee.exe D infile outfile + + unpack infile with header to outfile + +lzee.exe d infile outfile + + unpack infile without header to outfile + + header is unpacked size in little endian 32bit integer + +``` + +## original LZE readme.txt + +``` +------------------------------------------------------------------------ +lze LZSS亜種データ圧縮/展開ツール +------------------------------------------------------------------------ + + +------------------------------------------------------------------------ +■ 履歴 + +・20080228a + 最初のバージョン。 + +------------------------------------------------------------------------ +■ 概要 + +LZSS亜種圧縮/展開アルゴリズムにより作られたデータ圧縮/展開ツールとデコー +ダです。 +デコーダはアセンブラでわずか100ステップ程度で書かれており、非常に高速に +動作します。 +圧縮データはzipで圧縮した場合の20~30%増程度となります。 + +------------------------------------------------------------------------ +■ インストール方法 + +win32コマンドラインツールとそのソースであり、インストールは特に必要あり +ません。 + +------------------------------------------------------------------------ +■ 使用方法 + + lze.exe e infile outfile + infileを圧縮してoutfileへ出力します。 + + lze.exe d infile outfile + 圧縮済みのinfileを展開してoutfileへ出力します。 + + lzed.exe infile outfile + 圧縮済みのinfileを展開してoutfileへ出力します。 + lzedec.cを使用します。 + +------------------------------------------------------------------------ +■ ソースと歴史的経緯 + + lzedec.c Cによるデコーダ + lzedec_8086.asm MASM(8086)アセンブラによるデコーダ + 入力・出力ともに1セグメント内のみ有効 + lzedec_x68k.has has(MC68000)アセンブラによるデコーダ + +デコーダの対象CPUが古いものしかないのは、歴史的理由によるものです。 + +lzeの圧縮方式は、TONBE氏のX68000用汎用データ圧縮プログラム「BZ.X」を元に +作られています。 +TONBE氏のBZ.Xは、F&I氏のX68000用実行ファイル圧縮プログラム「lzx」を元に +作られています。 +F&I氏のlzxは、Fabrice Bellard氏のMS-DOS用実行ファイル圧縮プログラム +「LZEXE」を元に作られています。 +これらはいずれもソースコードが公開されておらず、リバースエンジニアリング +によって作られ、実行ファイルのみが公開されてきました。 + +本lzeは、当方の学習用および実務用として1995年に作られたものですが、これ +らの圧縮方式をソースコードとして残しておくために公開するものです。 + +------------------------------------------------------------------------ +■ その他 + +このプログラムおよびソースコードは、一切の制限なく使用・改造・配布等を +行うことができます。 + +-- +Hiroaki GOTO as GORRY : 後藤 浩昭 +E-mail: gorry@hauN.org +Homepage: http://GORRY.hauN.org/ + +[EOF] +```