;**********************************************************;
;* ZD v1.1 - Text to Binary Decoder, Better than UUENCODE *;
;* Companion Program to ZE.  Fast, Small - 190 Bytes!     *;
;*                                                        *;
;*                    By Tenie Remmel                     *;
;**********************************************************;

Ideal

Model Tiny
P186
CodeSeg
Org 100h

Proc        Program

            mov ah,3Fh         ;Read file/device
            xor bx,bx          ;handle for STDIN
            mov dx,1024        ;Start at DS:1K
            mov cx,63488       ;62K bytes (max)
            int 21h            ;DOS services

            mov si,1024        ;SI, DI = 1K
            mov di,si

            mov ah,'A'         ;AH = 'A'
            call GetDigit      ;First digit
            shl al,4           ;Shift over
            mov ch,al          ;Put in CH
            call GetDigit      ;Second digit
            or ch,al           ;OR into CH
            call GetDigit      ;Third digit
            shl al,4           ;Shift over
            mov cl,al          ;Put in CL
            call GetDigit      ;Last digit
            or cl,al           ;OR into CL
            push cx            ;Save numbytes
            jmp InpLoop

InpLoop:    lodsb              ;Load byte
            cmp al,21h         ;< 21h?
            jb InpLoop         ;Get new byte
            cmp al,'}'         ;Check for right bracket
            je Done            ;It's a right bracket, done
            ja InpLoop         ;Get new byte
            dec si             ;Re-load that byte
            lodsw              ;Load word

            xor dh,dh          ;Clear DH
            cmp al,40h         ;Adjust for at-sign
            jl AL_ok           ;which is char 40h
            dec ax
AL_ok:      cmp ah,40h
            jl AH_ok
            dec ah

AH_ok:      sub ax,2121h       ;Adjust to binary
            mov dl,ah          ;Save remainder
            mov ah,91          ;Multiply by 91
            mul ah
            add ax,dx          ;Add in remainder
            call Out13         ;Output 13 bits
            jmp InpLoop

Done:       mov ah,40h         ;Write file/device
            mov bx,1           ;handle for STDOUT
            pop cx             ;Number of bytes
            mov dx,1024        ;Start at DS:1K
            int 21h            ;DOS services

            ret                ;Exit

EndP        Program

BitBuf      dw 0               ;The bit buffer

Proc        GetDigit

DLoop:      lodsb
            cmp al,'A'
            jb DLoop
            cmp al,'P'
            ja DLoop
            sub al,'A'
            ret

EndP        GetDigit


BitCnt      db 0               ;The bit counter

Proc        Out13

            push ax bx cx      ;Save registers
            mov dx,[BitBuf]    ;Load buffer in DX
            mov cl,[BitCnt]    ;Load count in CL
            mov bl,cl          ;Count in BL also
            and cl,7           ;CL = shift count
            shl ax,3           ;Adjust AX
            mov ch,al          ;Save low 5 bits in CH
            xor al,al          ;Clear AL
            shr ax,cl          ;Adjust AX
            or dx,ax           ;Put byte in buffer
            mov al,dh          ;Shift byte out
            mov dh,dl
            xor dl,dl          ;Clear DL

            stosb              ;Store byte
            mov ah,ch          ;Get low 5 bits
            xor al,al          ;Clear AL
            shr ax,cl          ;Adjust AX
            or dx,ax           ;Put bits in buffer
            add bl,5           ;Adjust bit count
            cmp bl,8           ;Byte in buffer?
            jb Done1           ;If not, done
            mov al,dh          ;Shift byte out
            mov dh,dl
            xor dl,dl          ;Clear DL
            stosb              ;Store byte
            sub bl,8           ;Adjust bit count
Done1:      mov [BitBuf],dx    ;Save buffer
            mov [BitCnt],bl    ;Save bit count
            pop cx bx ax       ;Restore register
            ret                ;Return

EndP        Out13

End Program
