# HG changeset patch # User Pascal Bellard # Date 1692091255 0 # Node ID d5c772484b59caea95e74421e848b68c494b584c # Parent 5e2b41f82f137177ce544c18cbd5676ec7b69372 linux: rewrite stuff/pack diff -r 5e2b41f82f13 -r d5c772484b59 linux/receipt --- a/linux/receipt Sun Aug 13 19:51:00 2023 +0000 +++ b/linux/receipt Tue Aug 15 09:20:55 2023 +0000 @@ -53,8 +53,7 @@ S2bin bootloader S2bin helper S2bin unpacklz4 - cp $stuff/pack . - sh ./pack --build + cp $stuff/pack $stuff/un*.S . sed -i '/config %config:/{NNNps/config %config:/%config:/}' Makefile && sed -i 's/^config %config:/config:/' Makefile @@ -69,6 +68,7 @@ yes '' | make ARCH=i386 HOSTCC=gcc config make ARCH=i386 CC=gcc HOSTCC=gcc -j 4 bzImage cp arch/i386/boot/bzImage arch/i386/boot/bzImage.made.386 + sh ./pack --build arch/i386/boot/bzImage.made.386 grep -q "CONFIG_MODULES=y" .config && make ARCH=i386 CC=gcc HOSTCC=gcc -j 4 modules && @@ -97,12 +97,12 @@ mkdir $fs/boot cp -a $src/pack $fs/boot/ cp -a $src/bundle.sh $fs/boot/bundle - cp -a $src/editcmdline.bin $fs/boot/cmdline.bin + cp -a $src/cmdline.bin $fs/boot/ + cp -a $src/editcmdline.bin $fs/boot/ for i in '' .386 ; do [ -s $src/arch/i386/boot/bzImage$i ] || continue cp -a $src/arch/i386/boot/bzImage$i $fs/boot/ - dd if=$src/bootloader.bin of=$fs/boot/bzImage$i conv=notrunc - dd if=$src/cmdline.bin bs=1 seek=$(setup_code $fs/boot/bzImage$i) of=$fs/boot/bzImage$i conv=notrunc + dd if=$src/bootloader.bin of=$fs/boot/bzImage$i conv=notrunc 2> /dev/null cp -a $src/System.map$i $fs/boot/ cp -a $src/.config$i $fs/boot/config$i done @@ -131,9 +131,10 @@ for i in $1/boot/*.386 ; do [ "$CPU586" = "yes" ] && rm -f $i || mv -f $i ${i%.386} done 2> /dev/null + [ -s $1/boot/cmdline ] && cat $1/boot/cmdline | sed 's/^ *//' | \ + dd of=$1/boot/bzImage conv=notrunc bs=1 seek=768 count=3072 && + dd if=$1/boot/cmdline.bin bs=1 seek=$(setup_code $1/boot/bzImage) of=$1/boot/bzImage conv=notrunc [ "$EDIT_CMDLINE" ] && - dd if=$1/boot/cmdline.bin bs=1 seek=$(setup_code $1/boot/bzImage) of=$1/boot/bzImage conv=notrunc - [ -s $1/boot/cmdline ] && cat $1/boot/cmdline | sed 's/^ *//' | \ - dd of=$1/boot/bzImage conv=notrunc bs=1 seek=768 count=3072 + dd if=$1/boot/editcmdline.bin bs=1 seek=$(setup_code $1/boot/bzImage) of=$1/boot/bzImage conv=notrunc $1/boot/pack $1/boot/bzImage } diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/pack --- a/linux/stuff/pack Sun Aug 13 19:51:00 2023 +0000 +++ b/linux/stuff/pack Tue Aug 15 09:20:55 2023 +0000 @@ -1,98 +1,111 @@ #!/bin/sh +get() +{ + echo $(od -j $(($1)) -N ${3:-2} -t u${3:-2} -An "$2") +} + if [ "$1" = "--build" ]; then #install-begin - while read type pack args; do - grep -q "#define COMPRESSION.*$type" unpacklz4.S || continue - sed -i "s/COMPRESSOR/$pack/;s/COMPRESSION/$pack $args/" $0 - done </dev/null | uuencode -m - | sed -e \ - '/^helper\.bin$/r/dev/stdin' -e '/^helper\.bin$/d' -i $0 - sed '/install-begin$/,/install-end$/d' -i $0 - exit + header=$(($(get 0x201 $2 1)+2)) + sed "s|OFS|$((header+0x200))|g" -i $0 + for zip in zx0 lzma lz4 lzsa1 lzsa2 ; do + ZIP=$(echo $zip | sed 'y/almsxz/ALMSXZ/') + sed "/endzip:/ { + h + r un$zip.S + g ; N +}" unpack.S > unpack$zip.S + top=$((0x7900)) + [ "$zip" = "lzma" ] && top=$((0x3900)) + # cc -DTOP=0x7900 [-DSAVEREGS] [-DHEADER=0x38|-DTARGET=[0|0x1F2|0x200]] -o unpack.o -Wa,-a=unpack.lst -c unpack.S +# cc -DTOP=$top -DSAVEREGS -DHEADER=$header -o un$zip.o -Wa,-a=un$zip.lst -c unpack$zip.S + cc -DTOP=$top -DHEADER=$header -o un$zip.o -Wa,-a=un$zip.lst -c unpack$zip.S + objcopy --only-section=.text -O binary un$zip.o un$zip.bin + uuencode -m - < un$zip.bin | sed -e "/^${ZIP}_CODE\$/r/dev/stdin" -e "/^${ZIP}_CODE\$/d" -i $0 + start=$((0x$(sed '/start$/!d;s|.*text:00000||;s| .*||' un$zip.lst))) + moved=$((0x$(sed '/moved$/!d;s|.*text:0*||;s| .*||' un$zip.lst))) + sed "s|${ZIP}_START|$start|;s|${ZIP}_MOVED|$moved|" -i $0 + done + sed '/install-begin$/,/install-end$/d' -i $0 ; exit fi #install-end ddq() { dd "$@" 2> /dev/null } -word() +patch() { - n=$1; for i in $(seq 1 1 ${2:-2}); do - printf '\\\\x%02X' $(($n & 255)) - n=$(($n >> 8)) - done | xargs echo -en + xargs echo -en | ddq bs=1 seek=$2 conv=notrunc of=$1 } -store() +add() { - word $2 "$4" | ddq bs=1 conv=notrunc of="$3" seek=$(($1)) + local tmp=$(($1+$(get $2 $3))) + printf '\\\\x%02X\\\\x%02X' $((tmp&255)) $((tmp/256)) | patch /tmp/bz$$name $2 } -get() -{ - echo $(od -j $(($1)) -N ${3:-2} -t u${3:-2} -An "$2") -} +[ ! -s "$1" ] && echo "Usage: $0 bzImage [salvador|lzma|lz4|lzsa1|lzsa2|zx0]" && exit 1 -helper() -{ -uudecode << EOT -helper.bin +linux="$1" +zipper="$2" +setup=$(get 0x1F1 $linux 1) + +while read zip start moved cmd ; do + [ "$zipper" ] && [ "$zip" != "$zipper" ] && continue + which ${cmd%% *} || continue + case "$zip" in + salvador|zx0) + uudecode - > /tmp/unzip$$ < /tmp/unzip$$ < /tmp/unzip$$ < /tmp/unzip$$ < /tmp/unzip$$ < /tmp/bz$$.zz && mv /tmp/bz$$.zz /tmp/bz$$.z + sz1=$(stat -c %s /tmp/bz$$.z) + sz2=$(stat -c %s /tmp/unzip$$) + ddq if=/tmp/unzip$$ bs=1 skip=$start count=$((moved-start)) >> /tmp/bz$$name + add $sz1 $((start+2+0x200)) /tmp/bz$$name + add $sz1 $((start+5+0x200)) /tmp/bz$$name + cat /tmp/bz$$.z >> /tmp/bz$$name + ddq if=/tmp/unzip$$ bs=1 skip=$moved >> /tmp/bz$$name + x=$(((sz1+sz2+0x1FF)&0xFE00)) + printf '\\\\x%02X' $((x/512)) | patch /tmp/bz$$name 497 + ddq if=/dev/zero bs=1 count=$((x-sz1-sz2)) >> /tmp/bz$$name + ddq if=$linux bs=512 skip=$((1+setup)) >> /tmp/bz$$name -[ ! -s "$1" ] && echo "Usage: $0 bzImage" && exit 1 + mv /tmp/bz$$name $linux + rm /tmp/bz$$ /tmp/bz$$.z + break +done < /dev/null ; then - -# boot + head param -param=$((514+$(get 0x201 $1 1))) -ddq if=$1 bs=1 count=$param > /tmp/setup$$ - -# unlz4 + data -uudecode >> /tmp/setup$$ << EOT -unpacklz4.bin -EOT -setupsz=$(get 0x1F1 $1 1) -ddq if=$1 bs=1 skip=$param count=$(($setupsz*512-$param+512)) | \ - COMPRESSION >> /tmp/setup$$ - -# version string -word $(get 0x20E $1) >> /tmp/setup$$ -word $setupsz 1 >> /tmp/setup$$ -setupend=$(stat -Lc %s "/tmp/setup$$") -versionofs= -version="$(ddq if=$1 bs=1 skip=$((0x200+$(get 0x20E $1))) | strings | sed q)" -if grep --help 2>&1 | grep -q byte-offset; then - versionofs=$(grep -obaF "$version" /tmp/setup$$ | sed 's/:.*//') -fi -if [ -z "$versionofs" ]; then - versionofs=$(stat -c %s /tmp/setup$$) - echo -en "$version\0" >> /tmp/setup$$ -fi -store 0x20E $(($versionofs-512)) /tmp/setup$$ - -helpersz=$(helper | wc -c) -newsetupsz=$((($(stat -c %s /tmp/setup$$)+$helpersz-1)/512)) -[ $newsetupsz -lt 4 ] && newsetupsz=4 - -if [ $newsetupsz -lt $setupsz ]; then - while [ $(($setupend + $helpersz)) -gt $((512 + 512*$newsetupsz)) ]; do - newsetupsz=$(($newsetupsz+1)) - done -# ddq of=/tmp/setup$$ bs=512 seek=$(($newsetupsz+1)) count=0 - store 0x1F1 $newsetupsz /tmp/setup$$ 1 - helper | ddq bs=1 of=/tmp/setup$$ \ - seek=$((512 + 512*$newsetupsz - $helpersz)) - ddq if=$1 bs=512 skip=$((1+$setupsz)) >> /tmp/setup$$ - cp /tmp/setup$$ $1 -fi -rm -f /tmp/setup$$ - -fi diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/unlz4.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux/stuff/unlz4.S Tue Aug 15 09:20:55 2023 +0000 @@ -0,0 +1,230 @@ +// Lz4Decode: +#ifndef FLAT32 +// input ds:si=inStream, es:di=outStream +// output outStream[], ds:si, es:di + .code16 +#define AX %ax +#define BX %bx +#define CX %cx +#define SI %si +#define DI %di +#else +// input esi=inStream, edi=outStream +// output outStream[], ds:esi, es:edi + .code32 +#define AX %eax +#define BX %ebx +#define CX %ecx +#define SI %esi +#define DI %edi +#endif + +#if defined(FLAT16OUT) || defined(ONLY8086) +#define cAX %ax +#define cCX %cx +#define cDX %dx +#else +#define cAX %eax +#define cCX %ecx +#define cDX %edx +#endif + +#define ARCHIVE_MAGICNUMBER 0x184C2102 + +//#define PARANOIA // cover rare cases, optional + +lz4main: +#ifdef PARANOIA + cld +# if !defined(FLAT32) && !defined(FLAT16OUT) + xorl %cx, %cx + call lz4mov +# endif +#endif +#if defined(FLAT16OUT) || defined(ONLY8086) + lodsw // get chunkSize +# ifndef NO_LZ4_HEADER + cmpw $ARCHIVE_MAGICNUMBER&0xFFFF, %ax +# endif + xchg %ax, %dx + lodsw +# ifndef NO_LZ4_HEADER + jne chkeof + cmpw $ARCHIVE_MAGICNUMBER>>16, %ax + je lz4main +chkeof: +# endif +# ifdef PARANOIA + orw %ax, %dx // end of file ? + je lz4quit +# endif +# ifndef FLAT16OUT + xchgw %ax, %bp + subw $1, %dx + sbbw $0, %bp +# endif +#else + lodsl // get chunkSize +# ifndef NO_LZ4_HEADER + cmpl $ARCHIVE_MAGICNUMBER, %eax + je lz4main +# endif +# ifdef PARANOIA + orl %eax, %eax // end of file ? + je lz4quit +# endif + xchgl %eax, %edx +#endif +lz4chunk: // uncompress chunk + lodsb // get token + pushw %ax +#ifdef ONLY8086 + movb $4, %cl + shrb %cl, %al +#else + shrb $4, %al +#endif + call lz4len // get literal length +#if !defined(FLAT16OUT) && defined(ONLY8086) + subw %cx, %dx // count literal + sbbw $0, %bp +#else + sub cCX, cDX // count literal +#endif +#if !defined(FLAT32) && !defined(FLAT16OUT) && (!defined(FLAT16) || !defined(PARANOIA)) +#define NeedLz4mov + call lz4mov // copy literals +#else + rep movsb +#endif + popw %bx +#if !defined(FLAT16OUT) && defined(ONLY8086) + subw $1+2, %dx // count token & string address + sbbw $0, %bp + jb lz4quit +lz4cont: +#else + sub $1+2, cDX // count token & string address + jbe lz4quit +#endif + lodsw // get string address + xchg AX, BX + call lz4len // get string length + add $4, CX +#if !defined(FLAT32) && !defined(FLAT16OUT) + pushw %ds + pushw %si + movw %di, %si + subw %bx, %si + movw %es, %ax + jnc axok + subb $0x10, %ah +axok: +.macro norm reg + movw %si, \reg + andw $0xF, %si +# ifdef ONLY8086 + pushw %cx + movb $4, %cl + shrw %cl, \reg +# else + shrw $4, \reg +# endif + addw \reg, %ax + movw %ax, %ds + movw %di, \reg + andw $0xF, %di +# ifdef ONLY8086 + shrw %cl, \reg + popw %cx +# else + shrw $4, \reg +# endif + movw %es, %ax + addw \reg, %ax + movw %ax, %es +.endm +# if !defined (NeedLz4mov) + norm %bx + rep movsb +# else + call lz4movStr // copy string +# endif + popw %si + popw %ds +#else +# ifdef FASTFILL + cmp $FASTFILL,BX + jbe lz4fast +# endif +lz4notfast: + xchg AX, SI + mov DI, SI + sub BX, SI +# ifdef ONLY8086 +lz4movsb: + movsb %es:(SI), %es:(DI) // NMOS 8088/8086 workaround. + loop lz4movsb +# else + rep movsb %es:(SI), %es:(DI) +# endif + xchg AX, SI +# ifdef FASTFILL +lz4fast: +# if FASTFILL == 1 + movb %es:-1(DI), %al + rep stosb +# endif +# if FASTFILL >= 2 + movw %es:-2(DI), %ax + je lz4fastword + movb %al, %ah +lz4fastword: + shr $1, CX + rep stosw + jnc lz4chunk + stosb +# endif +# endif + jmp lz4chunk +#endif + +#if defined(NeedLz4mov) +# if defined(PARANOIA) +lz4movlp: + xchgw %ax, %cx + movw $0x7800, %cx + rep movsw + xchgw %ax, %cx + sub $0xF0, %ch +# endif +lz4mov: + movw %ds, %ax +lz4movStr: + norm %bx +# if defined(PARANOIA) + cmp $0xFF, %ch // catch FFFX case + jz lz4movlp +# endif + rep movsb + ret +#endif + +lz4len: // get length in %ecx + and $0xF, cAX + mov cAX, cCX + cmpb $0xF, %al + jne lz4quit +lz4len2: + lodsb +#if !defined(FLAT16OUT) && defined(ONLY8086) + subw $1, %dx // remaining chunk size + sbbw $0, %bp +#else + dec cDX // remaining chunk size +#endif + add AX, CX + cmpb $0xFF, %al + je lz4len2 +lz4quit: + ret diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/unlzma.S --- a/linux/stuff/unlzma.S Sun Aug 13 19:51:00 2023 +0000 +++ b/linux/stuff/unlzma.S Tue Aug 15 09:20:55 2023 +0000 @@ -97,11 +97,11 @@ #ifndef FLAT32 * input ds:si=inStream, es:di=outStream * output outStream[], ds:si, es:di - .code16 + .code 16 #else * input esi=inStream, edi=outStream * output outStream[], esi, edi - .code32 + .code 32 #endif */ @@ -252,13 +252,7 @@ // int matchByte = outStream[nowPos - rep0]; -#if defined(FLAT32) || defined(FLAT16OUT) - mov nowPos(BP), BX - sub rep0(BP), BX - movb (BX), %bl -#else call DicoRep02ESDI // %bl = outStream[nowPos - rep0]; -#endif // do { // int bit; @@ -674,26 +668,12 @@ lzd13z: // previousByte = outStream[nowPos - rep0]; // outStream[nowPos++] = previousByte; + + call outcharDico // %bl = outStream[nowPos++] = outStream[nowPos - rep0] + // } while(--len != 0); -#if defined(FLAT32) || defined(FLAT16OUT) - push SI - mov nowPos(BP), SI - sub rep0(BP), SI -lzd13zflat: -# ifdef FLAT32 - lodsb %ds:(SI) -# else - lodsb %es:(SI) -# endif - call outchar - loop lzd13zflat - pop SI -#else - call outcharDico // %bl = outStream[nowPos++] = outStream[nowPos - rep0] loop lzd13z -#endif - // } /* char/string */ // } @@ -704,18 +684,13 @@ // //RC_NORMALIZE; // //*inSizeProcessed = (SizeT)(Buffer - inStream); *outSizeProcessed = nowPos; // return LZMA_RESULT_OK; -#if !defined(FLAT32) && !defined(FLAT16OUT) call Dico2ESDI // set es & di (rep0 = 0) -#else - movw nowPos(BP), DI -#endif lea ws2(BP), SP // dealloc ret // } // al = outStream[nowPos - rep0]; -#if !defined(FLAT32) && !defined(FLAT16OUT) /* * output es:di, al * scratch bh, cl, flags @@ -732,6 +707,7 @@ */ Dico2ESDI: +#if !defined(FLAT32) && !defined(FLAT16OUT) # ifdef ONLY8086 pushw %ax movw nowPos(%bp), %bx @@ -759,6 +735,17 @@ shrl $4, %ebx # endif movw %bx, %es +#else + mov nowPos(BP), DI + jnc Dico2ESDIz + sub rep0(BP), DI +Dico2ESDIz: +#endif +#ifdef FLAT32 + movb (DI), %bl +#else + movb %es:(%di), %bl +#endif ret outcharDico: @@ -786,12 +773,6 @@ clc call Dico2ESDI stosb -#else -outchar: - movw nowPos(%bp), DI - stosb - movw DI, nowPos(%bp) -#endif xchg AX, BX // previous byte // int posState = (int)((nowPos) & posStateMask); @@ -809,13 +790,13 @@ andb $((1 << PROP_LP) -1), posState2(BP) # endif #endif -#if !defined(FLAT32) && !defined(FLAT16OUT) - inc nowPos(BP) -# if defined(ONLY8086) +#ifdef ONLY8086 + incw nowPos(BP) jnz incnowPosDone incw nowPos+2(BP) incnowPosDone: -# endif +#else + incl nowPos(BP) #endif ret diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/unlzsa1.S --- a/linux/stuff/unlzsa1.S Sun Aug 13 19:51:00 2023 +0000 +++ b/linux/stuff/unlzsa1.S Tue Aug 15 09:20:55 2023 +0000 @@ -1,143 +1,211 @@ -// based on -// decompress_small.S - space-efficient decompressor implementation for 8088 -// -// Copyright (C) 2019 Emmanuel Marty -// -// 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. - -// --------------------------------------------------------------------------- -// Decompress raw LZSA1 block -// inputs: -// * %ds:%si: raw LZSA1 block -// * %es:%di: output buffer -// --------------------------------------------------------------------------- - +// Lzsa1Decode: +#ifndef FLAT32 +// input ds:si=inStream, es:di=outStream +// output outStream[], ds:si, es:di .code16 -lzsa1_decompress: - //pushw %di // remember decompression offset - //cld // make string operations (lods, movs, stos..) move forward - -lzsa1_decode_token: - xorb %ah, %ah // clear %ah - lodsb // read token byte: O|LLL|MMMM - movw %ax,%bx // keep token in %bl - - andb $0x70, %al // isolate literals length in token (LLL) - je lzsa1_check_offset_size // if LLL=0, we have no literals; goto match -#ifdef ONLY8086 - movb $4, %cl - shrb %cl, %al // shift literals length into place +#define AX %ax +#define BX %bx +#define SI %si +#define DI %di #else - shrb $4, %al // shift literals length into place +// input esi=inStream, edi=outStream +// output outStream[], ds:esi, es:edi + .code32 +#define AX %eax +#define BX %ebx +#define SI %esi +#define DI %edi #endif - cmpb $7, %al // LITERALS_RUN_LEN? - jne lzsa1_got_literals // no, we have the full literals count from the token, go copy +MATCH_RUN_LEN = 15 +LITERALS_RUN_LEN = 7 +MIN_MATCH_SIZE = 3 +MIN_LITERALS_SIZE = 0 - lodsb // grab extra length byte - addb $7, %al // add LITERALS_RUN_LEN - jnc lzsa1_got_literals // if no overflow, we have the full literals count, go copy - je lzsa1_big_literals +#define PACKED_ONLY // assume no copy block, optional +//#define PARANOIA // cover rare cases, optional + +.macro shrclw cnt,obj +#ifdef ONLY8086 + movb \cnt, %cl + shrw %cl, \obj +#else + shrw \cnt, \obj +#endif +.endm - movb $1, %ah // add 256 (I'd prefer 'xchgb %al, %ah' max 1791 instead of 511) - lodsb // grab single extra length byte - .byte 0x3C // mask lodsw with cmpb $0xAD, %al - // (*like jmp short lzsa1_got_literals but faster) - -lzsa1_big_literals: - lodsw // grab 16-bit extra length - -lzsa1_got_literals: +#ifdef FLAT16OUT +#define RAW_FORMAT +#endif +lzsa1main: +#ifdef PARANOIA + cld +#endif +#ifndef RAW_FORMAT +# ifndef NO_LZSA1_HEADER + lodsw + cmpw $0x9E7B, %ax // magic + jne lzsa1main + lodsb +// cmpb $0, %al // lzsa1 +// jne lzsa1main +# endif + xorw %ax, %ax + xchgw %ax, %di + shrclw $4, %ax + jmp lzsa1blockz // %di *MUST* be paragraph aligned +# ifndef PACKED_ONLY +lzsa1copy: + movsb // handle 64K case + decw %cx + rep movsb // copy block +# endif +lzsa1block: // uncompress chunk + movw $0x1000, %ax +lzsa1blockz: + movw %es, %bx + addw %ax, %bx + movw %bx, %es +# ifndef FLAT16 + movw %si, %ax + andw $0xf, %si + shrclw $4, %ax + movw %ds, %bx + addw %ax, %bx + movw %bx, %ds +# endif + lodsw // block size xchgw %ax, %cx -#ifdef USE_MOVSW - shrw $1, %cx - rep movsw - adcw %cx, %cx + movw %cx, %dx + lodsb +# ifndef PACKED_ONLY + orb %al, %al + js lzsa1copy + jne lzsa1full // 64Kb block +# endif + jcxz lzsa1quit // bail if we hit EOD +lzsa1full: + addw %si, %dx #endif - rep movsb // copy %cx literals from %ds:%si to %es:%di - -lzsa1_check_offset_size: +lzsa1chunk: // uncompress chunk + lodsb // get token O|LLL|MMMM + movb %al, %bl // keep token in bl + shrclw $4, %ax // shift literals length into place + movw $LITERALS_RUN_LEN+256*MIN_LITERALS_SIZE, %cx + call lzsa1len // %ch = LITERALS_RUN_LEN + rep movsb // copy %cx literals from %ds:%si to %es:%di +#ifndef RAW_FORMAT + cmpw %dx, %si + je lzsa1block // bail if we hit EOD +#endif +#ifdef FLAT32 + orl $-1, %eax +#endif testb %bl, %bl // check match offset size in token (O bit) - js lzsa1_get_long_offset - - decw %cx - xchgw %ax, %cx // %ah to 0xff - %cx was zero from the rep movsb above + js lzsa1LongOfs +#ifndef FLAT32 + movb $-1, %ah // set offset bits 15-8 to 1 +#endif lodsb .byte 0x3C // mask lodsw with cmpb $0xAD, %al - // (*like jmp short lzsa1_get_match_length but faster) - -lzsa1_get_long_offset: - lodsw // Get 2-byte match offset - -lzsa1_get_match_length: - xchgw %ax, %bx // %bx: match offset %ax: original token - andb $0xF, %al // isolate match length in token (MMMM) - addb $3, %al // add MIN_MATCH_SIZE - - cmpb $0x12, %al // MATCH_RUN_LEN? - jne lzsa1_got_matchlen // no, we have the full match length from the token, go copy - - lodsb // grab extra length byte - addb $0x12, %al // add MIN_MATCH_SIZE + MATCH_RUN_LEN - jnc lzsa1_got_matchlen // if no overflow, we have the entire length - je lzsa1_big_matchlen - - movb $1, %ah // add 256 (I'd prefer 'xchgb %al, %ah' max 3071 instead of 511) - lodsb // grab single extra length byte - .byte 0x3C // mask lodsw with cmpb $0xAD, %al - // (*like jmp short lzsa1_got_matchlen but faster) -lzsa1_big_matchlen: - lodsw // grab 16-bit length - -lzsa1_got_matchlen: - xchgw %ax, %cx // copy match length into %cx - jcxz lzsa1_done_decompressing // bail if we hit EOD - xchgw %ax, %si // save %si (current pointer to compressed data) - leaw (%bx,%di), %si // %es:%si now points at back reference in output data -#ifdef USE_MOVSW - cmpw $-2, %bx - jae lzsa1_store - shrw $1, %cx - rep movsw %es:(%si), %es:(%di) - adcw %cx, %cx -#endif - rep movsb %es:(%si), %es:(%di) // copy match - xchgw %ax, %si // restore %ds:%si - jmp lzsa1_decode_token // go decode another token -#ifdef USE_MOVSW -lzsa1_store: - je lzsa1_store_word - lodsb %es:(%si) - movb %al, %ah - .byte 0x3D // mask lodsw with cmpb $0x26AD, %ax - // (*like jmp short lzsa1_store_byte but faster) -lzsa1_store_word: - lodsw %es:(%si) -lzsa1_store_byte: - shrw $1, %cx - rep stosw - adcw %cx, %cx - rep stosb - xchgw %ax, %si // restore %ds:%si - jmp lzsa1_decode_token // go decode another token +lzsa1LongOfs: + lodsw + xchg AX, BX // %bx: match offset %ax: original token + movw $MATCH_RUN_LEN+256*MIN_MATCH_SIZE, %cx + call lzsa1len +#ifdef RAW_FORMAT + jcxz lzsa1quit // bail if we hit EOD #endif -lzsa1_done_decompressing: -// popw %ax // retrieve the original decompression offset -// xchgw %ax, %di // compute decompressed size -// subw %di, %ax - ret // done +#if !defined(FLAT16OUT) && !defined(FLAT32) + xchg AX, SI // save %si + lea (BX,DI), SI + pushw %ds + movw %es, %bp + cmpw %si, %di + jnc lzsa1sameSeg + pushw %si +# ifdef ONLY8086 + pushw %cx +# endif + shrclw $4, %si +# ifdef ONLY8086 + popw %cx +# endif + lea -4096(%bp,%si), %bp + popw %si + andw $0xF, %si +lzsa1sameSeg: + movw %bp, %ds +# ifdef FASTFILL + cmp $-FASTFILL,BX + jae lzsa1fast +# endif + rep movsb +lzsa1chunkz: + popw %ds +#else +# ifdef FASTFILL + cmp $-FASTFILL,BX + jae lzsa1fast +# endif + xchg AX, SI // save %si + lea (BX,DI), SI +# ifdef ONLY8086 +lzsa2movsb: + movsb %es:(SI), %es:(DI) // NMOS 8088/8086 workaround. + loop lzsa2movsb +# else + rep movsb %es:(SI), %es:(DI) +# endif +#define lzsa1chunkz lzsa1chunk +#endif + xchg AX, SI // restore %si + jmp lzsa1chunk +#ifdef FASTFILL +lzsa1fast: +# if FASTFILL == 1 +# if !defined(FLAT16OUT) && !defined(FLAT32) + lodsb +# else + movb %es:(BX,DI), %al +# endif + rep stosb +# endif +# if FASTFILL == 2 +# if !defined(FLAT16OUT) && !defined(FLAT32) + lodsw +# else + movw %es:(BX,DI), %ax +# endif + je lzsa1fastword + movb %ah, %al +lzsa1fastword: + shr $1, CX + rep stosw + jnc lzsa1chunkz + stosb +# endif + jmp lzsa1chunkz +#endif + +lzsa1len: // get length in %ecx + andb %cl, %al + cbw // clear %ah + cmpb %al, %cl + jne lzsa1minNumber // S=0-6, L=0-14 %cx = %ch + %al if (%al & %cl != %cl) + addb %al, %ch + lodsb +lzsa1minNumber: + addb %ch, %al + jnc lzsa1gotNumber // 0-255 %cx = %ch + %cl + byte if (%al & %cl == %cl && %ch + %cl + byte < 0x100) + movb %al, %ah // S=256-1791, L=256-4607 or S=256-511, L=256-511 + jne lzsa1midNumber + lodsw // 0-65535 %cx = word if (%al & %cl == %cl && %ch + %cl + byte == 0x100) + .byte 0x3C // mask lodsb with cmpb $0xAC, %al +lzsa1midNumber: + lodsb // %cx = (%ch + %cl + byte)*256 + byte2 if (%al & %cl == %cl && %ch + %cl + byte > 0x100) +lzsa1gotNumber: + xchgw %ax, %cx +lzsa1quit: + ret diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/unlzsa2.S --- a/linux/stuff/unlzsa2.S Sun Aug 13 19:51:00 2023 +0000 +++ b/linux/stuff/unlzsa2.S Tue Aug 15 09:20:55 2023 +0000 @@ -1,177 +1,279 @@ -// based on -// decompress_small.S - space-efficient decompressor implementation for 8088 -// -// Copyright (C) 2019 Emmanuel Marty -// -// 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. - -// --------------------------------------------------------------------------- -// Decompress raw LZSA2 block -// inputs: -// * %ds:%si: raw LZSA2 block -// * %es:%di: output buffer -// --------------------------------------------------------------------------- - +// Lzsa2Decode: +#ifndef FLAT32 +// input ds:si=inStream, es:di=outStream +// output outStream[], ds:si, es:di .code16 -lzsa2_decompress: - //pushw %di // remember decompression offset - //cld // make string operations (lods, movs, stos..) move forward - - xorw %cx, %cx - movw $0x100, %bx - xorw %bp, %bp - -lzsa2_decode_token: - movw %cx, %ax // clear %ah - %cx is zero from above or from after rep movsb in lzsa2_copy_match - lodsb // read token byte: XYZ|LL|MMMM - movw %ax,%dx // keep token in %dl - - andb $0x18, %al // isolate literals length in token (LL) -#ifdef ONLY8086 - movb $3, %cl - shrb %cl, %al // shift literals length into place +#define AX %ax +#define BX %bx +#define SI %si +#define DI %di #else - shrb $3, %al // shift literals length into place +// input esi=inStream, edi=outStream +// output outStream[], ds:esi, es:edi + .code32 +#define AX %eax +#define BX %ebx +#define SI %esi +#define DI %edi #endif - cmpb $3, %al // LITERALS_RUN_LEN_V2? - jne lzsa2_got_literals // no, we have the full literals count from the token, go copy +MATCH_RUN_LEN = 7 +LITERALS_RUN_LEN = 3 +MIN_MATCH_SIZE = 2 +MIN_LITERALS_SIZE = 0 - call lzsa2_get_nibble // get extra literals length nibble - addb %cl, %al // add len from token to nibble - cmpb $0x12, %al // LITERALS_RUN_LEN_V2 + 15 ? - jne lzsa2_got_literals // if not, we have the full literals count, go copy - lodsb // grab extra length byte - addb $0x12, %al // overflow? - jnc lzsa2_got_literals // if not, we have the full literals count, go copy +#define PACKED_ONLY // assume no copy block, optional +//#define PARANOIA // cover rare cases, optional + +.macro shrcl cnt,obj +#ifdef ONLY8086 + movb \cnt, %cl + shr %cl, \obj +#else + shr \cnt, \obj +#endif +.endm - lodsw // grab 16-bit extra length +#ifdef FLAT16OUT +#define RAW_FORMAT +#endif +lzsa2main: +#ifdef PARANOIA + cld +#endif +#ifndef RAW_FORMAT +# ifndef NO_LZSA2_HEADER + lodsw + cmpw $0x9E7B, %ax // magic + jne lzsa2main + lodsb +// testb $0x20, %al // lzsa2 +// je lzsa2main +# endif + xorw %ax, %ax + cwd // no nibble stored + xchgw %ax, %di + shrcl $4, %ax + jmp lzsa2blockz // %di *MUST* be paragraph aligned +# ifndef PACKED_ONLY +lzsa2copy: + movsb // handle 64K case + decw %cx + rep movsb // copy block +# endif +lzsa2block: // uncompress chunk + movw $0x1000, %ax +lzsa2blockz: + movw %es, %bx + addw %ax, %bx + movw %bx, %es +# ifndef FLAT16 + movw %si, %ax + andw $0xf, %si + shrcl $4, %ax + movw %ds, %bx + addw %ax, %bx + movw %bx, %ds +# endif + lodsw // block size + xchgw %ax, %cx + movw %cx, %bp + lodsb +# ifndef PACKED_ONLY + orb %al, %al + js lzsa2copy + jne lzsa2full // 64Kb block +# endif + jcxz lzsa2quit // bail if we hit EOD +lzsa2full: + addw %si, %bp +#else + movb $0, %dh // no nibble stored +#endif +#ifdef FLAT32 + orl $-1, %ebx // set offset bits 31-16 to 1 +#endif +lzsa2chunk: // uncompress chunk + lodsb // get token XYZ|LL|MMM + pushw %ax // keep token + movw $LITERALS_RUN_LEN+256*MIN_LITERALS_SIZE, %cx + shrb %cl, %al // shift literals length into place + call lzsa2len // %cl = LITERALS_RUN_LEN + rep movsb // copy %cx literals from %ds:%si to %es:%di + popw %ax // restore token +#ifndef RAW_FORMAT + cmpw %bp, %si + je lzsa2block // bail if we hit EOD +#endif + pushw %ax // save token +// Decode XYZ bits to SZC flags + andb $0xE0, %al // filter XYZ + movb %al, %ah + orb $0xDF, %al + incw %ax + sahf // ah=SZ.A.P.C + je no_nibble_in_offset // Y=1 -lzsa2_got_literals: - xchgw %ax, %cx - rep movsb // copy %cx literals from %ds:%si to %es:%di + call getNibble // get nibble for offset bits 0-3, kill %cl + sahf + rclb $1, %al + xorb $0xE1, %al // set offset bits 7-5 to 1 + sahf + cbw // set offset bits 15-8 to 1 +// 00Z 5-bit offset: read a nibble for offset bits 1-4 and use the inverted bit Z of the token as bit 0 of the offset. +// set bits 5-15 of the offset to 1. + jns get_match_length // 5-bit offset +//10Z 13-bit offset: read a nibble for offset bits 9-12 and use the inverted bit Z for bit 8 of the offset, +// then read a byte for offset bits 0-7. set bits 13-15 of the offset to 1. +// substract 512 from the offset to get the final value. + subb $2, %al // substract 512, clear C + jmp get_match_length_1 - testb $0xC0, %dl // check match offset size in token (X bit) - js lzsa2_rep_match_or_large_offset - - //cmpb $0x40, %dl // check if this is a 5 or 9-bit offset (Y bit) - // discovered via the test with bit 6 set - xchgw %ax, %cx // clear %ah - %cx was zero from the rep movsb above - jne lzsa2_offset_9_bit - - // 5 bit offset - cmpb $0x20, %dl // test bit 5 - call lzsa2_get_nibble_x - jmp lzsa2_dec_offset_top - -lzsa2_offset_9_bit: // 9 bit offset - lodsb // get 8 bit offset from stream in A - decb %ah // set offset bits 15-8 to 1 - testb $0x20, %dl // test bit Z (offset bit 8) - je lzsa2_get_match_length -lzsa2_dec_offset_top: - decb %ah // clear bit 8 if Z bit is clear - // or set offset bits 15-8 to 1 - jmp lzsa2_get_match_length - -lzsa2_rep_match_or_large_offset: - //cmpb $0xC0, %dl // check if this is a 13-bit offset or a 16-bit offset/rep match (Y bit) - jpe lzsa2_rep_match_or_16_bit - - // 13 bit offset - - cmpb $0xA0, %dl // test bit 5 (knowing that bit 7 is also set) - xchgb %al, %ah - call lzsa2_get_nibble_x - subb $2, %al // substract 512 - jmp lzsa2_get_match_length_1 - -lzsa2_rep_match_or_16_bit: - testb $0x20, %dl // test bit Z (offset bit 8) - jne lzsa2_repeat_match // rep-match - - // 16 bit offset - lodsb // Get 2-byte match offset - -lzsa2_get_match_length_1: - xchgb %al, %ah - lodsb // load match offset bits 0-7 - -lzsa2_get_match_length: - xchgw %ax, %bp // %bp: offset -lzsa2_repeat_match: - xchgw %ax, %dx // %ax: original token - andb $7, %al // isolate match length in token (MMM) - addb $2, %al // add MIN_MATCH_SIZE_V2 - - cmpb $9, %al // MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2? - jne lzsa2_got_matchlen // no, we have the full match length from the token, go copy - - call lzsa2_get_nibble // get extra literals length nibble - addb %cl, %al // add len from token to nibble - cmpb $0x18, %al // MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2 + 15? - jne lzsa2_got_matchlen // no, we have the full match length from the token, go copy - - lodsb // grab extra length byte - addb $0x18, %al // overflow? - jnc lzsa2_got_matchlen // if not, we have the entire length - je lzsa2_done_decompressing // detect EOD code - - lodsw // grab 16-bit length - -lzsa2_got_matchlen: - xchgw %ax, %cx // copy match length into %cx - xchgw %ax, %si // save %si (current pointer to compressed data) - leaw (%bx,%di), %si // %es:%si now points at back reference in output data - rep movsb %es:(%si), %es:(%di) // copy match - xchgw %ax, %si // restore %si - jmp lzsa2_decode_token // go decode another token - -//lzsa2_done_decompressing: -// popw %ax // retrieve the original decompression offset -// xchgw %ax, %di // compute decompressed size -// subw %di, %ax -// ret // done - -lzsa2_get_nibble_x: - cmc // carry set if bit 4 was set - rcrb $1, %al - call lzsa2_get_nibble // get nibble for offset bits 0-3 - orb %cl, %al // merge nibble - rolb $1, %al - xorb $0xE1, %al // set offset bits 7-5 to 1 -lzsa2_done_decompressing: +getNibble: + xorb $0xF0, %dh // toggle nibble stored flags + movb %dh, %al + jns gotnibble + lodsb + movb $0xF0, %dh + orb %al, %dh + shrcl $4, %al +gotnibble: +lzsa2quit: ret -lzsa2_get_nibble: - negb %bh // nibble ready? - jns lzsa2_has_nibble - - xchgw %ax, %bx - lodsb // load two nibbles - xchgw %ax, %bx +no_nibble_in_offset: + movb $-1, %ah // set offset bits 15-8 to 1 + jns offset_9_bit // X=0 Y=1 + jc repeat_match // rep-match X=1 Y=1 Z=1 +//110 16-bit offset: read a byte for offset bits 8-15, then another byte for offset bits 0-7. + lodsb // Get 2-byte match offset +get_match_length_1: + xchgb %al, %ah -lzsa2_has_nibble: -#ifdef ONLY8086 - movb $4, %cl // swap 4 high and low bits of nibble - rorb %cl, %bl +offset_9_bit: // Z=C +// 01Z 9-bit offset: read a byte for offset bits 0-7 and use the inverted bit Z for bit 8 of the offset. +// set bits 9-15 of the offset to 1. + sbbb %ch, %ah // clear bit 8 if Z bit is clear (%ch == 0) + lodsb // load match offset bits 0-7 +get_match_length: + xchgw %ax, %bx // bx: offset +repeat_match: +//111 repeat offset: reuse the offset value of the previous match command. + + popw %ax // restore original token in %al + movw $MATCH_RUN_LEN+256*MIN_MATCH_SIZE, %cx + call lzsa2len +#if !defined(ENHANCED_FORMAT) && defined(RAW_FORMAT) + je lzsa2quit // bail if we hit EOD in (%si-2) +#endif + +#if !defined(FLAT16OUT) && !defined(FLAT32) + xchg AX, SI // save %si + lea (BX,DI), SI + pushw %ds +# ifndef RAW_FORMAT + pushw %bp // save end +# endif + movw %es, %bp + cmpw %si, %di + jnc lzsa2sameSeg + pushw %si +# ifdef ONLY8086 + pushw %cx +# endif + shrcl $4, %si +# ifdef ONLY8086 + popw %cx +# endif + lea -4096(%bp,%si), %bp + popw %si + andw $0xF, %si +lzsa2sameSeg: + movw %bp, %ds +# ifdef FASTFILL + cmp $-FASTFILL,BX + jae lzsa2fast +# endif + rep movsb +lzsa2chunkz: +# ifndef RAW_FORMAT + popw %bp // restore end +# endif + popw %ds #else - rorb $4, %bl +# ifdef FASTFILL + cmp $-FASTFILL,BX + jae lzsa2fast +# endif + xchg AX, SI // save %si + lea (BX,DI), SI +# ifdef ONLY8086 +lzsa2movsb: + movsb %es:(SI), %es:(DI) // NMOS 8088/8086 workaround. + loop lzsa2movsb +# else + rep movsb %es:(SI), %es:(DI) +# endif +#define lzsa2chunkz lzsa2chunk #endif - movb $0xF, %cl - andb %bl, %cl + xchg AX, SI // restore %si + jmp lzsa2chunk +#ifdef FASTFILL +lzsa2fast: +# if FASTFILL == 1 +# if !defined(FLAT16OUT) && !defined(FLAT32) + lodsb +# else + movb %es:(BX,DI), %al +# endif + rep stosb +# endif +# if FASTFILL == 2 +# if !defined(FLAT16OUT) && !defined(FLAT32) + lodsw +# else + movw %es:(BX,DI), %ax +# endif + je lzsa2fastword + movb %ah, %al +lzsa2fastword: + shr $1, CX + rep stosw + jnc lzsa2chunkz + stosb +# endif + jmp lzsa2chunkz +#endif + +lzsa2len: // get length in %cx + andb %cl, %al + cbw // clear %ah + cmpb %al, %cl + jne lzsa2minNumber // S=0-2, L=0-6 %cx = %ch + %al if (%al & %cl != %cl) + addb %al, %ch + call getNibble // kill %cl + cmp $0xF, %al + jne lzsa2minNumber // %cx = %ch + %cl + nibble if (%al & %cl == %cl && nibble != 0xF) + addb %al, %ch + lodsb +lzsa2minNumber: + addb %ch, %al + jnc lzsa2gotNumber // 0-255 %cx = %ch + %cl + 0xF + byte if (%al & %cl == %cl && nibble == 0xF && %ch + %cl + 0xF + byte < 0x100) +#ifdef ENHANCED_FORMAT + decw %ax + je lzsa2maxNumber +# ifdef RAW_FORMAT + jns lzsa2midNumber + popw %ax + ret // bail if we hit EOD +lzsa2midNumber: +# endif + xchgb %al, %ah // S=256-4351, L=256-5887 + lodsb // %cx = (%ch + %cl + 0xE + byte)*256 + byte2 if (%al & %cl == %cl && nibble == 0xF && %ch + %cl + 0xF + byte > 0x100) + .byte 0xB1 // mask lodsw with movb $0xAD, %cl +lzsa2maxNumber: +#endif + lodsw // 0-65535 %cx = word if (%al & %cl == %cl && nibble == 0xF && %ch + %cl + 0xF + byte == 0x100) +lzsa2gotNumber: + xchgw %ax, %cx ret diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/unpack.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux/stuff/unpack.S Tue Aug 15 09:20:55 2023 +0000 @@ -0,0 +1,62 @@ +// cc -DTOP=topmem [-DSAVEREGS] [-DHEADER=0x38|-DTARGET=[0|0x1F2|0x200]] -o unpack.o -Wa,-a=unpack.lst -c unpack.S +// objcopy --only-section=.text -O binary unpack.o unpack.bin + + .code16 + +.zero: +#ifdef HEADER + .org HEADER +# define TARGET 0x200+HEADER +#else +# ifndef TARGET +# define TARGET 0x200 +# endif +#endif + +#define PACKSZ 0 + +.start: +#ifdef SAVEREGS + pushaw +#else + std +#endif + movw $PACKSZ+.end-.moved, %cx + movw $0x200+PACKSZ+.end-1, %si + movw $TOP-1, %di + pushw %ds + popw %es +#ifdef SAVEREGS + std +#endif + rep movsb + cld + leaw 1(%di), %si + movw $TARGET, %di +#ifdef SAVEREGS +// jmp TOP-0x200+.endzip-.end + jmp TOP-0x200+.endzip-.end+.zero-.moved+2 // ??? +#else + pushw %cx +// jmp TOP-0x200+.unzip-.end + jmp TOP-0x200+.unzip-.end+.zero-.moved+2 // ??? +#endif + +// ============================================================================== + +#define FLAT16 +#define FLAT16OUT +#define RAW_FORMAT +#define NO_LZ4_HEADER +#define NO_LZMA_HEADER + +.moved: +.unzip: +.endzip: +#ifdef SAVEREGS + call .unzip + popaw + pushw $0 + ret +#endif +.end: diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/unpacklz4.S --- a/linux/stuff/unpacklz4.S Sun Aug 13 19:51:00 2023 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -// objdump -D -b binary -mi386 -Maddr16,data16 mbr - - .code16 - .org 0 - -// LZ4 LZSA1 LZSA2 or LZMA -#define COMPRESSION_LZ4 -#define HOLE 0x4000 -#define DS_OFS 0x0200 - -start: - cld -#define packed_moved HOLE+0x200+packed - movw $packed_moved-next, %di - xorw %si, %si - movw %di, %cx - pushw %ds - popw %es - rep movsb %ds:(%si), %es:(%di) // move setup - pushw %cs // CS - pushw %cx // IP = 0 - //pushaw - call packed_moved -next: - popw %bx - leaw DS_OFS+start-next(%bx), %di - leaw DS_OFS+packed-next(%bx,%si), %si -#if defined(COMPRESSION_LZMA) - call unlzma -#elif defined(COMPRESSION_LZSA2) - call unlzsa2 -#elif defined(COMPRESSION_LZSA1) - call unlzsa1 -#else - -#define ARCHIVE_MAGICNUMBER 0x184C2102 -#define NEGATIVE_OFFSETS 0 // non standard hack -#define LENGTH_16BITS 0 // non standard hack -#define BYTE_RLE 0 - -lz4main: - lodsl // get chunkSize - //cmpl $ARCHIVE_MAGICNUMBER, %eax - //je lz4main - //lodsw - addw %si, %ax - xchgw %ax, %dx - //lodsw - jmp lz4chunk // %cx = 0 - -lz4len: // get length in %cx - andw $0xF, %ax - cmpb $0xF, %al - xchgw %ax, %cx - jne lz4quit -lz4len2: - lodsb - addw %ax, %cx - cmpb $0xFF, %al -#if LENGTH_16BITS - jne lz4quit - lodsw - addw %ax, %cx -#else - je lz4len2 -#endif -lz4quit: - ret - -#if BYTE_RLE - movb -1(%di), %al - rep stosb %es:(%di) // fill string - jmp lz4chunk -#endif - -lz4string: - lodsw // get string offset - xchgw %ax, %bx - call lz4len // get string length - add $4, %cx // minimum match is 4 -#if BYTE_RLE - decw %bx - jz lz4rle -# if NEGATIVE_OFFSETS - incw %bx -# else - notw %bx -# endif -#endif - pushw %si -#if NEGATIVE_OFFSETS || BYTE_RLE - leaw (%bx,%di), %si -#else - movw %di, %si - subw %bx, %si -#endif -#ifdef USE_MOVSW -# if NEGATIVE_OFFSETS || BYTE_RLE - cmpw $-2, %bx - jb lzs4_move_words -# else - cmpw $2, %bx - ja lzs4_move_words -# endif - lodsw %es:(%si) - je lzs4_store_word - movb %al, %ah -lzs4_store_word: - shrw $1, %cx - rep stosw %es:(%di) - adcw %cx, %cx - rep stosb %es:(%di) -lzs4_move_words: - shrw $1, %cx - rep movsw %es:(%si), %es:(%di) - adcw %cx, %cx -#endif - rep movsb %es:(%si), %es:(%di) // copy string - popw %si - -lz4chunk: // uncompress chunk - lodsb // get token - movb %al, %bl - shrb $4, %al - call lz4len // get literal length -#ifdef USE_MOVSW - shrw $1, %cx - rep movsw %ds:(%si), %es:(%di) - adcw %cx, %cx -#endif - rep movsb %ds:(%si), %es:(%di) // copy literals - cmpw %dx, %si - jb lz4string -#endif -done: - movw $0x020E, %di - movsw // version string - movw $0x01F1, %di - movsb // setup size - //popaw - retf - -#if defined(COMPRESSION_LZMA) -#define FLAT16 1 -#define FLAT16OUT 1 -#define NO_LZMA_HEADER 1 -unlzma: -#include "unlzma.S" -#elif defined(COMPRESSION_LZSA2) -unlzsa2: -#include "unlzsa2.S" -#elif defined(COMPRESSION_LZSA1) -unlzsa1: -#include "unlzsa1.S" -#endif - -packed: diff -r 5e2b41f82f13 -r d5c772484b59 linux/stuff/unzx0.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux/stuff/unzx0.S Tue Aug 15 09:20:55 2023 +0000 @@ -0,0 +1,127 @@ +#ifndef FLAT32 +// input ds:si=inStream, es:di=outStream +// output outStream[], ds:si, es:di + .code16 +#define BX %bx +#define SI %si +#define DI %di +#else +// input esi=inStream, edi=outStream +// output outStream[], ds:esi, es:edi + .code32 +#define BX %ebx +#define SI %esi +#define DI %edi +#endif + +// unzx0_8088.S - ZX0 decompressor for 8088 - 73 bytes - NASM +// +// inputs: +// * ds:si: start of compressed data +// * es:di: start of decompression buffer +// +// Copyright (C) 2021 Emmanuel Marty +// ZX0 compression (c) 2021 Einar Saukas, https://github.com/einar-saukas/ZX0 +// +// 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. + +zx0_decompress: +// cld // make string operations go forward + movb $0x80, %al // initialize empty bit queue + // plus bit to roll into carry + stc + sbb BX, BX // initialize rep-offset to 1 + +.literals: +#if !defined(FLAT16) && !defined(FLAT32) + movw $32768, %dx + cmpw %dx, %si // assume 32767 literals max + jb .si_ok + subw %dx, %si + movw %ds, %dx + addb $8, %dh + movw %dx, %ds +.si_ok: +#endif + call .get_elias // read number of literals to copy + rep movsb // copy literal bytes + + addb %al, %al // shift bit queue, and high bit into carry + jc .get_offset // if 1: read offset, if 0: rep-match + + call .get_elias // read rep-match length (starts at 1) + +#if !defined(FLAT16OUT) && !defined(FLAT32) + jmp .copy_match +.fix_di: + subw $256, %di + movw %es, %dx + addw $16, %dx + movw %dx, %es +.copy_match: + cmpw $-32640, %di // assume 32639 max window + ja .fix_di +#else +.copy_match: +#endif + push SI // save si (current pointer to compressed data) + lea (BX,DI), SI // point to destination in es:di + offset in bx +#ifdef ONLY8086 +.copy_loop: + movsb %es:(SI), %es:(DI) // copy matched bytes using NMOS 8088/8086 workaround. + loop .copy_loop +#else + rep movsb %es:(SI), %es:(DI) // copy matched bytes +#endif + pop SI // restore si + + addb %al, %al // read 'literal or match' bit + jnc .literals // if 0: go copy literals + +.get_offset: + movb $0xfe, %cl // initialize value to FEh + call .elias_loop // read high byte of match offset, set carry + incb %cl // obtain negative offset high byte + je .done // exit if EOD marker + + movb %cl, %bh // transfer negative high byte into bh + movw $1, %cx // initialize match length value to 1 + movb (%si), %bl // read low byte of offset + 1 bit of len + incw %si // inc instruction keep carry set + // set high bit that is shifted into bit 15 + rcrw $1, %bx // shift len bit into carry/offset in place + call .elias_bt // if len bit is set, no need for more + // else read rest of elias-encoded match length + incw %cx // fix match length + jmp .copy_match // go copy match + +.get_elias: + movw $1, %cx // initialize value to 1 +.elias_loop: + addb %al, %al // shift bit queue, and high bit into carry + jnz .got_bit // queue not empty, bits remain + lodsb // read 8 new bits + adcb %al, %al // shift bit queue, and high bit into carry +.got_bit: +.elias_bt: + jc .got_elias // done if control bit is 1 + addb %al, %al // read data bit + adcw %cx, %cx // shift into cx + jmp .elias_loop // keep reading +.got_elias: +.done: + ret