home *** CD-ROM | disk | FTP | other *** search
- comment ~
-
- Deziper
-
- ~
- _TEXT SEGMENT PUBLIC 'CODE'
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
- ORG 100H
- START: JMP MAIN
-
-
- ; DATA AREA
- ; ---------
- DB CR,SPACE,SPACE,SPACE,CR,LF
-
- COPYRIGHT DB "PCUNZIP 1.0 Copyright (c) 1992 Michael J. Mefford",CR,LF
- FIRST_RIGHTS DB "First Published in PC Magazine, March 31, 1992",CR,LF,LF
-
- SYNTAX DB "Syntax: PCUNZIP filename [\path] [/v] [/e] [/o] [/?]",CR,LF,LF
-
- DB "/e filespec = extract specific file",CR,LF
- DB "/v [filespec] = view zipped files",CR,LF
- DB "/o = overwrite any existing files",CR,LF,LF
-
- DB "Putting a filename after /e will extract a specific; required",CR,LF
- DB "Putting a filename after /v will list a specific file",CR,LF,LF,"$"
-
- CR = 13
- LF = 10
- CTRL_Z = 26
- SPACE = 32
- BELL = 7
- Y_SCAN = 15H
- N_SCAN = 31H
- TRUE = 1
- FALSE = 0
-
- KILOBYTES = 1024
- PARAGRAPH = 16
-
- DTA = 80H
-
- MATCHING STRUC
- RESERVED DB 21 DUP (?)
- ATTR DB ?
- DW ?
- DW ?
- DW ?
- DW ?
- FILE_NAME DB 13 DUP (?)
- MATCHING ENDS
-
- LOCAL_HEADER STRUC
- SIGNATURE DB "PK",3,4
- EXTRACT_VER DW ?
- BIT_FLAG DW ?
- ZIP_TYPE DW ?
- FILE_TIME DW ?
- FILE_DATE DW ?
- CRC_32 DW ?,?
- COMPRESS_SIZE DW ?,?
- UNCOMPRESS_SIZE DW ?,?
- FILENAME_LEN DW ?
- EXTRA_FIELD_LEN DW ?
- LOCAL_HEADER ENDS
-
- LOCAL_SIG DB "PK",3,4
- CENTRAL_SIG DB "PK",1,2
-
- ;Unshrink stuff
-
- MIN_CODE_SIZE = 9
- MAX_CODE_SIZE = 13
- SPECIAL_CODE = 256
- FIRST_FREE = 257
- TRIE_SIZE = (1 SHL MAX_CODE_SIZE) + 1
- FREE = -1
-
- PREFIX_SIZE = TRIE_SIZE * 2 ;Word
- SUFFIX_SIZE = TRIE_SIZE * 2 ;Char + void
- READ_SIZE = 127 * 512
- WRITE_SIZE = 127 * 512
- DIR_SIZE = 66
- LOCAL_STACK = 512
- PREFIX_P = PREFIX_SIZE / PARAGRAPH
- SUFFIX_P = SUFFIX_SIZE / PARAGRAPH
- READ_P = READ_SIZE / PARAGRAPH
- WRITE_P = WRITE_SIZE / PARAGRAPH
-
- ;Explode stuff
-
- SF_TREE STRUC
- BIT_LENGTH DB ?
- VALUE DB ?
- TREE_CODE DW ?
- SF_TREE ENDS
-
- LIT_TREE_SIZE = 256 * SIZE SF_TREE
- LEN_TREE_SIZE = 64 * SIZE SF_TREE
- DIST_TREE_SIZE = 64 * SIZE SF_TREE
- TREE_ENTRIES = - 2
-
- ;Expand stuff
-
- FOLLOWER STRUC
- SET_LEN DB ?
- SET DB 32 DUP (?)
- PAD DB ?
- FOLLOWER ENDS
-
-
- READ_SEG DW ?
- WRITE_SEG DW ?
-
- DIR_LEN = 65
- NAME_LEN = 12
- ZIP_LEN = DIR_LEN + NAME_LEN
- OUTFILE DB NAME_LEN DUP (?), 0
- ZIP_NAME DB ZIP_LEN DUP (?), 0
- DIR_NAME DB ZIP_LEN DUP (?), 0
- SPECIFIC_NAME DB NAME_LEN DUP (?), 0
- VIEW_NAME DB 39 DUP (?)
- DB CR,LF,"$"
-
-
- SEARCH_LEN DW ZIP_LEN
- SEARCH_NAME DW ZIP_NAME
-
- FREE_NODE DW FIRST_FREE * 2
- EXTRACTOR DW ?
- RUNNING_CRC_32 DW ?,?
-
- BITS_LEFT DB ?
- CODE_BITS DB ?
- SAVE_BYTE DB ?
-
- ATTRIBUTE DB ?
- SPIN_CNT DB 0
- SPIN_INDEX DW 0
- SPINNERS DB "/|\"
-
- SPECIFIC_FLAG DB FALSE ;=TRUE if extract individual file.
- VIEW_FLAG DB FALSE ;=TRUE if view zipped files.
- EXTRACTED_FLAG DB FALSE ;=TRUE if a file was extracted.
- OVERWRITE_FLAG DB FALSE ;=TRUE if overwrite existing.
-
- ZIP_EXT DB ".ZIP"
- MEMORY_MSG DB "Not enough memory"
- CR_LF_LF DB LF
- CR_LF DB CR,LF,"$"
- ZIP_MSG DB "Zip header not found$"
- FAILED_MSG DB "Extracted file maybe corrupt",BELL,"$"
- DISK_MSG DB "Not enough free disk space to extract file$"
- ENCRYPTED_MSG DB "File is encrypted$"
- NOT_FOUND_MSG DB "File not found$"
- EXISTS_MSG DB " already exists. Overwrite (Y/N)?$"
- UNKNOWN_MSG DB "Unknown compression method$"
- INVALID_MSG DB "Invalid drive$"
- DIR_MSG DB "Invalid target directory$"
- SYNTAX_MSG DB "Syntax error$"
-
- ; CODE AREA
- ; ---------
- MAIN PROC NEAR
-
- CLD
-
- XOR BH,BH
- MOV AH,8
- INT 10H
- MOV ATTRIBUTE,AH
-
- MOV BX,OFFSET STACK_POINTER + 15
- MOV CL,4
- SHR BX,CL
- ADD BX,PREFIX_P + SUFFIX_P + READ_P + WRITE_P
- MOV AH,4AH ;Allocate memory.
- INT 21H
- JNC SETUP_STACK
- MOV DX,OFFSET MEMORY_MSG
- JMP SHORT ERROR_EXIT ;If not enough, exit.
-
- SETUP_STACK: MOV AX,OFFSET STACK_POINTER
- MOV SP,AX ;Set up stack.
- ADD AX,15
- MOV CL,4
- SHR AX,CL
- MOV CX,DS
- ADD AX,CX
- ADD AX,PREFIX_P + SUFFIX_P
- MOV READ_SEG,AX
- ADD AX,READ_P
- MOV WRITE_SEG,AX
-
- CALL PARSE
- JC ERROR_EXIT
- MOV DX,OFFSET ZIP_NAME
- XOR CX,CX
- MOV AH,4EH
- INT 21H
- JMP SHORT DO_EXTRACT
-
- NEXT_EXTRACT: CALL WRITE_CRLF
- NEXT_EXTRACT2: MOV BX,READ_HANDLE
- MOV AH,3EH
- INT 21H
-
- PUSH CS
- POP ES
- MOV AH,4FH
- INT 21H
- JNC DO_EXTRACT
-
- GOOD_EXIT: XOR AL,AL
- JMP SHORT EXIT
-
- DO_EXTRACT: MOV SI,OFFSET DTA.FILE_NAME
- MOV DI,OFFSET ZIP_NAME
- CALL FORM_NAME
-
- MOV DX,OFFSET ZIP_NAME
- MOV AX,3D00H
- INT 21H
- MOV DX,OFFSET NOT_FOUND_MSG
- JC ERROR_EXIT
-
- MOV READ_HANDLE,AX
- CALL EXTRACT
- JNC NEXT_EXTRACT
- CMP DX,OFFSET ZIP_MSG
- JZ NEXT_EXTRACT2
-
- ERROR_EXIT: PUSH DX
- CALL WRITE_CRLF
- POP DX
- CALL PRINT_STRING
- CALL WRITE_CRLFLF
- MOV DX,OFFSET COPYRIGHT
- CALL PRINT_STRING
- MOV AL,1
-
- EXIT: MOV AH,4CH
- INT 21H
-
- MAIN ENDP
-
- ;**************
- ; SUBROUTINES *
- ;**************
-
- ;OUTPUT: CF=1 if parse fail.
-
- PARSE: MOV SEARCH_LEN,ZIP_LEN
- MOV SEARCH_NAME,OFFSET ZIP_NAME
- MOV SI,81H
- NEXT_PARSE: CALL PARSE_DELIMIT
- LODSB
- CMP AL,CR
- JZ PARSE_DONE
- CMP AL,"-"
- JZ SWITCH
- CMP AL,"/"
- JNZ DO_FILENAME
- SWITCH: CALL PARSE_SWITCH
- JC PARSE_END
- JMP NEXT_PARSE
-
- DO_FILENAME: DEC SI
- MOV CX,SEARCH_LEN
- MOV DI,SEARCH_NAME
- CALL STORE_SEARCH
- MOV SEARCH_LEN,DIR_LEN
- MOV SEARCH_NAME,OFFSET DIR_NAME
- JMP NEXT_PARSE
-
-
- PARSE_DONE: MOV DX,OFFSET SYNTAX_MSG
- CMP BYTE PTR ZIP_NAME,0
- STC
- JZ PARSE_END
-
- MOV DX,OFFSET ZIP_NAME
- XOR CX,CX
- MOV AH,4EH
- INT 21H
- JNC FOUND_ZIP
- CALL TACK_ZIP
- MOV DX,OFFSET ZIP_NAME
- XOR CX,CX
- MOV AH,4EH
- INT 21H
- MOV DX,OFFSET NOT_FOUND_MSG
- JC PARSE_END
-
- FOUND_ZIP: CMP DIR_NAME,0
- JZ PARSE_END
-
- MOV SI,OFFSET DIR_NAME
- NEXT_DIR_END: LODSB
- OR AL,AL
- JNZ NEXT_DIR_END
- DEC SI
- DEC SI
- CMP BYTE PTR [SI],":"
- JZ PARSE_END
-
- MOV DX,OFFSET DIR_NAME
- MOV CX,10H
- MOV AH,4EH
- INT 21H
- MOV DX,OFFSET DIR_MSG
- JC PARSE_END
- TEST BYTE PTR DS:[DTA.ATTR],10H
- STC
- JZ PARSE_END
-
- CMP BYTE PTR [SI],"\"
- JZ PARSE_END
- MOV BYTE PTR [SI+1],"\"
- CLC
-
- PARSE_END: RET
-
- ;----------------------;
-
- PARSE_DELIMIT: LODSB
- CMP AL,CR
- JZ DELIMIT_END
- CMP AL,SPACE
- JBE PARSE_DELIMIT
- DELIMIT_END: DEC SI
- RET
-
- ;----------------------;
-
- PARSE_SWITCH: CALL PARSE_DELIMIT
- CMP AL,CR
- JZ SWITCH_ERROR
- LODSB
- AND AL,5FH
- CMP AL,"V"
- JNZ CK_O
- MOV VIEW_FLAG,TRUE
- CALL PARSE_DELIMIT
- CMP AL,CR
- JZ SWITCH_GOOD
- JMP SHORT DO_SPECIFIC
-
- CK_O: CMP AL,"O"
- JNZ CK_E
- MOV OVERWRITE_FLAG,TRUE
- JMP SHORT SWITCH_GOOD
-
- CK_E: CMP AL,"E"
- JNZ SWITCH_ERROR
- CALL PARSE_DELIMIT
- CMP AL,CR
- JZ SWITCH_ERROR
- MOV SPECIFIC_FLAG,TRUE
-
- DO_SPECIFIC: MOV CX,NAME_LEN
- MOV DI,OFFSET SPECIFIC_NAME
- CALL STORE_SEARCH
-
- SWITCH_GOOD: CLC
- JMP SHORT SWITCH_END
-
- SWITCH_ERROR: MOV DX,OFFSET SYNTAX_MSG
- STC
- SWITCH_END: RET
-
- ;----------------------;
- ; INPUT: DI-> storage; CX=length.
-
- STORE_SEARCH: LODSB
- CMP AL,CR
- JZ STORE_DONE
- CMP AL,SPACE
- JBE STORE_END2
- CMP AL,"a"
- JB STORE_SEARCH2
- CMP AL,"z"
- JA STORE_SEARCH2
- AND AL,5FH
- STORE_SEARCH2: STOSB
- LOOP STORE_SEARCH
- JMP SHORT STORE_END2
- STORE_DONE: DEC SI
- STORE_END2: RET
-
- ;----------------------;
-
- TACK_ZIP: MOV SI,OFFSET ZIP_NAME
- MOV CX,ZIP_LEN - 4
- NEXT_TACK: LODSB
- CMP AL,"."
- JZ TACK_IT
- CMP AL,0
- JZ TACK_IT
- LOOP NEXT_TACK
- JMP SHORT TACK_END
-
- TACK_IT: DEC SI
- MOV DI,SI
- MOV SI,OFFSET ZIP_EXT
- MOV CX,4
- REP MOVSB
-
- TACK_END: RET
-
- ;----------------------------------------------;
- ; INPUT: SI-> name; DI-> storage.
-
- FORM_NAME: PUSH SI
- MOV SI,DI
-
- NEW_END: MOV BX,SI
- FIND_END: LODSB
- CMP AL,":"
- JZ NEW_END
- CMP AL,"\"
- JZ NEW_END
- OR AL,AL
- JNZ FIND_END
-
- POP SI
- MOV DI,BX
- FORM_NAME2: LODSB
- STOSB
- OR AL,AL
- JNZ FORM_NAME2
- RET
-
- ;----------------------------------------------;
-
- ;OUTPUT: If CF=1 then DX = failed msg.
-
- EXTRACT: MOV BYTES_TO_READ[0],SIZE LOCAL_HEADER
- MOV BYTES_TO_READ[2],0
- CALL READ_ZIP
- JNC CK_HEADER
- JMP FAILED
-
- CK_HEADER: MOV ES,READ_SEG
- MOV SI,OFFSET LOCAL_SIG
- XOR DI,DI
- MOV CX,4
- REPZ CMPSB
- JZ PROCESS
-
- MOV SI,OFFSET CENTRAL_SIG
- XOR DI,DI
- MOV CX,4
- REPZ CMPSB
- JNZ PROCESS_ERR
- CLC
- JMP EXTRACT_END
-
- PROCESS_ERR: MOV DX,OFFSET ZIP_MSG
- PROCESS_ERR2: JMP FAILED2
-
- PROCESS: CALL PROCESS_HEADER
- JNC PROCESS2
- JMP FAILED2
- PROCESS2: CALL READ_ZIP
- JC LILLY_FAIL
-
- MOV BYTES_TO_READ[0],AX
- MOV BYTES_TO_READ[2],BX
- CALL GET_FILENAME
- JC EXTRACT
-
- MOV DX,OFFSET DIR_NAME
- XOR CX,CX
- MOV AH,3CH
- INT 21H
- LILLY_FAIL: JC FAILED
- MOV WRITE_HANDLE,AX
-
- MOV RUNNING_CRC_32[0],-1
- MOV RUNNING_CRC_32[2],-1
-
- CMP BYTES_TO_READ[0],0
- JNZ PROCESS3
- CMP BYTES_TO_READ[2],0
- JZ PROCESS4
-
- PROCESS3: CALL READ_ZIP
- JC FAILED
-
- MOV SAVE_BYTE,0
- MOV BITS_LEFT,0
-
- CALL [EXTRACTOR]
-
- PUSHF
- MOV AL,SPACE
- CALL SPIN_IT
- CALL WRITE_CRLFLF
- POPF
-
- JC FAILED
- CALL WRITE
- JC FAILED
-
- PROCESS4: MOV BX,WRITE_HANDLE
- MOV CX,TIME_STAMP
- MOV DX,DATE_STAMP
- MOV AX,5701H
- INT 21H
- JC FAILED
- MOV AH,3EH
- INT 21H
-
- CALL CK_CRC
- JC FAILED
-
- CMP BYTES_TO_READ[0],0
- JNZ FAILED
- CMP BYTES_TO_READ[2],0
- JNZ FAILED
- MOV EXTRACTED_FLAG,TRUE
- JMP EXTRACT
-
- FAILED: MOV DX,OFFSET FAILED_MSG
- FAILED2: STC
-
- EXTRACT_END: RET
-
- ;----------------------------------------------;
- ; INPUT:CX=FILENAME_LEN; OUTPUT: CF=1 if skipped.
-
- END_FILENAME DW ?
-
- GET_FILENAME: MOV AX,CS
- MOV ES,AX
- MOV DI,OFFSET OUTFILE
- PUSH DS
- MOV DS,READ_SEG
- XOR SI,SI
-
- NEXT_FILENAME: LODSB
- CMP AL,"/"
- JNZ STORE_NAME
- MOV DI,OFFSET OUTFILE
- JMP SHORT STORE_NAME2
-
- STORE_NAME: STOSB
- STORE_NAME2: LOOP NEXT_FILENAME
- MOV SI,DI
- XOR AL,AL
- STOSB
- POP DS
-
- MOV SI,OFFSET OUTFILE
- MOV DI,OFFSET DIR_NAME
- CALL FORM_NAME
- DEC DI
- MOV END_FILENAME,DI
-
- CALL VIEW_OR_SPEC
- JC FILENAME_END
-
- MOV DX,OFFSET DIR_NAME
- MOV AX,3D00H
- INT 21H
- CMC
- JNC FILENAME_END
-
- MOV BX,AX
- MOV AH,3EH
- INT 21H
-
- CMP OVERWRITE_FLAG,TRUE
- CLC
- JZ FILENAME_END
-
- CALL WRITE_FILENAME
- MOV DX,OFFSET EXISTS_MSG
- CALL PRINT_STRING
-
- CK_KEY: MOV AH,1 ;Is there a keystroke available.
- INT 16H
- JZ NEXT_KEY
- CLEAR_IT: XOR AH,AH
- INT 16H
- JMP CK_KEY
-
- NEXT_KEY: XOR AH,AH
- INT 16H
- CLC
- CMP AH,Y_SCAN
- JZ CONTINUE
- CMP AL,3 ;Ctrl break
- JNZ CK_N
- JMP GOOD_EXIT
- CK_N: CMP AH,N_SCAN
- JNZ NEXT_KEY
-
- MOV DX,BYTES_TO_READ[0]
- MOV CX,BYTES_TO_READ[2]
- MOV BX,READ_HANDLE
- MOV AX,4201H
- INT 21H
- STC
-
- CONTINUE: PUSHF
- CALL WRITE_CRLFLF
- POPF
-
- FILENAME_END: RET
-
- ;----------------------;
- ; OUTPUT: CF=1 of should not be extracted.
-
- VIEW_OR_SPEC: CMP VIEW_FLAG,TRUE
- JNZ CK_SPECIFIC
- CMP SPECIFIC_NAME,0
- JZ DO_DISPLAY
- CALL CK_MATCH
- JC ADVANCE_FILE
-
- DO_DISPLAY: CALL DISPLAY_NAME
- JMP SHORT ADVANCE_FILE
-
- CK_SPECIFIC: CMP SPECIFIC_FLAG,TRUE
- CLC
- JNZ V_OR_S_END
- CALL CK_MATCH
- JNC V_OR_S_END
-
- ADVANCE_FILE: MOV DX,BYTES_TO_READ[0]
- MOV CX,BYTES_TO_READ[2]
- MOV BX,READ_HANDLE
- MOV AX,4201H
- INT 21H
- JC V_OR_S_END
- CMC
-
- V_OR_S_END: RET
-
- ;----------------------;
- ; OUTPUT: CF=1 if no match.
-
- CK_MATCH: MOV SI,OFFSET SPECIFIC_NAME
- MOV DI,OFFSET OUTFILE
-
- NEXT_NAME: LODSB
- MOV AH,[DI]
- CMP AL,"*"
- JZ FIND_DOT
-
- CK_Q: CMP AL,"?"
- JNZ COMPARE_NAME
- OR AH,AH
- JZ NEXT_NAME
- CMP AH,"."
- JZ NEXT_NAME
- INC DI
- JMP NEXT_NAME
-
- COMPARE_NAME: INC DI
- CMP AL,AH
- JNZ NO_MATCH
- OR AL,AL
- JZ MATCH
- CMP AL,"."
- JNZ NEXT_NAME
- JMP SHORT NEXT_EXT
-
- FIND_DOT: LODSB
- CMP AL,"."
- JZ DO_OUTFILE
- OR AL,AL
- JNZ FIND_DOT
- DEC SI
-
- DO_OUTFILE: MOV AL,[DI]
- OR AL,AL
- JZ NEXT_EXT
- INC DI
- CMP AL,"."
- JNZ DO_OUTFILE
-
- NEXT_EXT: LODSB
- MOV AH,[DI]
- CMP AL,"*"
- JZ MATCH
- CMP AL,"?"
- JNZ COMPARE_EXT
- OR AH,AH
- JZ NEXT_EXT
- INC DI
- JMP NEXT_EXT
-
- COMPARE_EXT: INC DI
- CMP AL,AH
- JNZ NO_MATCH
- OR AL,AL
- JNZ NEXT_EXT
-
- MATCH: CLC
- JMP SHORT CK_MATCH_END
-
- NO_MATCH: STC
-
- CK_MATCH_END: RET
-
- ;----------------------;
-
- DISPLAY_NAME: MOV EXTRACTED_FLAG,TRUE
-
- MOV DI,OFFSET VIEW_NAME
- MOV AL,SPACE
- MOV CX,SIZE VIEW_NAME
- REP STOSB
-
- MOV SI,OFFSET OUTFILE ;Point to filename.
- MOV DI,OFFSET VIEW_NAME
- MOV CX,NAME_LEN ;Store 12 bytes of filename.
- JMP SHORT NEXT_STORE2
-
- EXTENSION: ADD DI,CX
- MOV CX,3
- SUB DI,CX
-
- NEXT_STORE2: LODSB ;Get a byte.
- OR AL,AL ;End of filename?
- JZ END_STORE ;If yes, finish with blanks.
- CMP AL,"." ;Is it the period?
- JZ EXTENSION
-
- STOSB ;Store byte.
- LOOP NEXT_STORE2 ;Get next byte.
- END_STORE: ADD DI,CX
-
- STORE_SIZE: PUSH DI ;Save pointer.
- ADD DI,8 ;Move to end of bytes field.
- MOV DX,SIZE_LOW ;Retrieve high and low words
- MOV AX,SIZE_HIGH ; of size in bytes.
- MOV BX,10
- STD ;Reverse direction.
- NEXT_SIZE: MOV CX,DX ;Low word in CX.
- XOR DX,DX ;Zero in high half.
- DIV BX ;Convert to decimal.
- XCHG AX,CX ;Retrieve low word.
- DIV BX
- XCHG AX,DX ;Retrieve remainder.
- ADD AL,"0" ;Convert to ASCII.
- STOSB ;Store it.
- MOV AX,CX ;Are we done?
- OR CX,DX
- JNZ NEXT_SIZE ;If no, divide again.
-
- CLD ;Back to forward direction.
- POP DI ;Retrieve pointer.
- ADD DI,11 ;Move to date field.
-
- STORE_DATE: MOV DX,DATE_STAMP ;Retrieve date.
- MOV AX,DX
- MOV CL,5 ;Shift to lowest bits.
- SHR AX,CL
- AND AX,1111B ;Mask off all but month.
- MOV CL,0FFH ;Flag as no leading zeros.
- MOV CH,"-" ;Delimiting character.
- CALL STORE_WORD ;Store it.
-
- MOV AX,DX ;Retrieve date.
- AND AX,11111B ;Mask off all but day.
- XOR CL,CL ;Flag include leading zeros.
- CALL STORE_WORD ;Store it.
-
- MOV AX,DX ;Retrieve date for last time.
- MOV CL,9
- SHR AX,CL ;Mask off all but year.
- ADD AX,80 ;Adjust to ASCII.
- CMP AX,100 ;Past year 2000?
- JB DISPLAY_DATE ;If no, display. Else, adjust for
- SUB AX,100 ; next century. (Planning ahead!)
- DISPLAY_DATE: XOR CL,CL ;Display leading zeros.
- MOV CH,SPACE
- CALL STORE_WORD ;Store it.
-
- TIME: INC DI ;Move to time field.
- MOV DX,TIME_STAMP ;Retrieve time.
- MOV AX,DX
- MOV CL,11 ;Shift to hours bits.
- SHR AX,CL
- PUSH AX
- CMP AX,12 ;Past noon?
- JBE MERIDIAN
- SUB AX,12 ;If yes, adjust.
- MERIDIAN: CMP AX,0 ;Midnight?
- JNZ NOT_MIDNIGHT
- MOV AX,12 ;If yes, adjust.
- NOT_MIDNIGHT: MOV CL,0FFH ;Suppress leading zeros.
- MOV CH,":"
- CALL STORE_WORD ;Store it.
-
- MOV AX,DX ;Retrieve time.
- MOV CL,5 ;Shift to minutes bits.
- SHR AX,CL
- AND AX,111111B ;Mask off all but minutes.
- XOR CL,CL
- POP DX ;Retrieve hours.
- MOV CH,"p" ;Assume PM.
- CMP DX,12 ;Is it PM?
- JAE PM
- MOV CH,"a" ;If no, AM.
-
- PM: CALL STORE_WORD ;Store it.
- MOV DX,OFFSET VIEW_NAME
- MOV AH,9H
- INT 21H
- RET
-
- ;-----------------------------------------------------------------------;
- ; Converts a two byte hex number to decimal followed by delimiter. ;
- ; INPUT: AX = hex number; BL = 10; CH = delimiter character to store. ;
- ; CL = 0 if zeros are to be stored; CL = -1 if leading zeros ignored. ;
- ; ES:DI points to storage. ;
- ;-----------------------------------------------------------------------;
- STORE_WORD: DIV BL ;Divide by ten.
- ADD AX,"00" ;Convert to ASCII.
- CMP CL,0 ;Are we to display leading zero?
- JZ STORE_IT ;If yes, store as is.
- CMP AL,"0" ;Is it a leading zero?
- JNZ STORE_IT ;If no, store it.
- MOV AL,SPACE ;Else, store a space.
- STORE_IT: STOSW
- MOV AL,CH ;Store delimiter character also.
- STOSB
- RET
-
- ;----------------------------------------------;
- ;OUTPUT: AX=COMPRESS_SIZE[0]; BX=COMPRESS_SIZE[2]; CX=FILENAME_LEN;
- ; CF=1 if failed.
-
- COMPRESS_FLAG DB ?
- TIME_STAMP DW ?
- DATE_STAMP DW ?
- FILE_CRC DW ?,?
- SIZE_HIGH DW ?
- SIZE_LOW DW ?
-
- REDUCE_L DW ?
- REDUCE_F DW ?
- REDUCE_D1 DB ?
- REDUCE_D2 DW ?
-
- PROCESS_HEADER:PUSH DS
- MOV DS,READ_SEG
- MOV AX,DS:BIT_FLAG
- MOV CS:COMPRESS_FLAG,AL
- TEST AX,1
- MOV DX,OFFSET ENCRYPTED_MSG
- JNZ PROCESS_FAIL
-
- CALL PROCESS_TYPE
- MOV DX,OFFSET UNKNOWN_MSG
- JC PROCESS_FAIL
-
- XOR DL,DL
- MOV AH,36H
- INT 21H
- CMP AX,0FFFFH
- MOV DX,OFFSET INVALID_MSG
- JZ PROCESS_FAIL
- MUL BX
- MUL CX
- SUB AX,DS:UNCOMPRESS_SIZE[0]
- SBB DX,DS:UNCOMPRESS_SIZE[2]
- MOV DX,OFFSET DISK_MSG
- JC PROCESS_FAIL
-
- MOV AX,DS:UNCOMPRESS_SIZE[0]
- MOV CS:SIZE_LOW,AX
- MOV AX,DS:UNCOMPRESS_SIZE[2]
- MOV CS:SIZE_HIGH,AX
-
- MOV CX,DS:FILENAME_LEN
- MOV DX,DS:EXTRA_FIELD_LEN
- ADD DX,CX
- MOV AX,DS:COMPRESS_SIZE[0]
- MOV BX,DS:COMPRESS_SIZE[2]
- MOV SI,DS:FILE_TIME
- MOV DI,DS:FILE_DATE
- MOV BP,DS:CRC_32[0]
- MOV CS:FILE_CRC[0],BP
- MOV BP,DS:CRC_32[2]
- CLC
- JMP SHORT PROCESS_END
-
- PROCESS_FAIL: STC
-
- PROCESS_END: POP DS
- MOV FILE_CRC[2],BP
- MOV BYTES_TO_READ[0],DX
- MOV TIME_STAMP,SI
- MOV DATE_STAMP,DI
- RET
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- PROCESS_TYPE: MOV BX,DS:ZIP_TYPE
- MOV AX,OFFSET UNSTORE
- OR BX,BX
- JZ STORE_EXTRACT
-
- MOV AX,OFFSET UNSHRINK
- DEC BX
- JZ STORE_EXTRACT
-
- MOV AX,OFFSET EXPAND
- MOV DX,7FH
- MOV CX,701H
- DEC BX
- JZ STORE_EXPAND
-
- MOV DX,3FH
- MOV CX,603H
- DEC BX
- JZ STORE_EXPAND
-
- MOV DX,1FH
- MOV CX,507H
- DEC BX
- JZ STORE_EXPAND
-
- MOV DX,0FH
- MOV CX,40FH
- DEC BX
- JNZ CK_EXPLODE
-
- STORE_EXPAND: MOV CS:REDUCE_L,DX
- MOV CS:REDUCE_F,DX
- MOV CS:REDUCE_D1,CH
- XOR CH,CH
- MOV CS:REDUCE_D2,CX
- JMP SHORT STORE_EXTRACT
-
- CK_EXPLODE: MOV AX,OFFSET EXPLODE
- DEC BX
- JZ STORE_EXTRACT
- STC
- JMP SHORT TYPE_END
-
- STORE_EXTRACT: MOV CS:EXTRACTOR,AX
- CLC
- TYPE_END: RET
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- CK_CRC: MOV AX,RUNNING_CRC_32[0]
- MOV DX,RUNNING_CRC_32[2]
- XOR AX,0FFFFH
- XOR DX,0FFFFH
- CMP AX,FILE_CRC[0]
- STC
- JNZ CRC_END
- CMP DX,FILE_CRC[2]
- STC
- JNZ CRC_END
- CLC
- CRC_END: RET
-
- ;**********************************************;
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- ;**********************************************;
-
- EXTRACT_MSG DB "Extracting $"
-
- UNSTORE: MOV DX,OFFSET EXTRACT_MSG
- CALL PRINT_STRING
- CALL WRITE_FILENAME
-
- UNSTORE_SPIN: CALL SPINNER
-
- NEXT_UNSTORE: INC SPIN_CNT
- JZ UNSTORE_SPIN
-
- MOV ES,READ_SEG
- MOV SI,READ_PTR
- CMP SI,BYTES_READ
- JZ GET_BYTES2
- MOV AL,ES:[SI]
- INC READ_PTR
- CALL STORE_CHAR
- JNC NEXT_UNSTORE
- CLC
- JMP SHORT UNSTORE_END
-
- GET_BYTES2: CALL READ_ZIP
- JNC NEXT_UNSTORE
- CLC
-
- UNSTORE_END: RET
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- EXPAND_MSG DB "Expanding $"
-
- STATE DW ?
- LAST_CHAR DB ?
-
- EXPAND: MOV DX,OFFSET EXPLODE_MSG
- CALL PRINT_STRING
- CALL WRITE_FILENAME
-
- MOV WRITE_FLAG,0
- MOV LAST_CHAR,0
- MOV STATE,OFFSET STATE_ZERO
-
- CALL LOAD_FOLLOWERS
- JC EXPAND_END
-
- EXPAND_SPIN: CALL SPINNER
-
- NEXT_EXPAND: INC SPIN_CNT
- JZ EXPAND_SPIN
-
- MOV AX,SIZE FOLLOWER
- MUL LAST_CHAR
- MOV BP,AX
-
- CMP BYTE PTR FOLLOWERS[BP],0
- JNZ GET_BIT
-
- MOV BL,8
- CALL GET_CODE
- JNC DO_EXPAND
- JMP SHORT EXPAND_END
-
- GET_BIT: MOV BL,1
- CALL GET_CODE
- JC EXPAND_END
- OR AL,AL
- JZ GET_FOLLOW
-
- MOV BL,8
- CALL GET_CODE
- JNC DO_EXPAND
- JMP SHORT EXPAND_END
-
- GET_FOLLOW: MOV BH,FOLLOWERS[BP]
- SUB BH,1
- JC EXPAND_ERR
- MOV BL,8
- JMP SHORT NEXT_BIT2
- NEXT_BIT: DEC BL
- NEXT_BIT2: SHL BH,1
- JNC NEXT_BIT
- CALL GET_CODE
- JC EXPAND_END
- MOV SI,AX
- INC SI
- MOV AL,FOLLOWERS[BP+SI]
- XOR AH,AH
-
- DO_EXPAND: MOV LAST_CHAR,AL
- CALL [STATE]
- JNC NEXT_EXPAND
- EXPAND_ERR: STC
- JMP SHORT EXPAND_END2
-
- EXPAND_END: CLC
- EXPAND_END2: RET
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- LOAD_FOLLOWERS:MOV BP,255 * SIZE FOLLOWER
- NEXT_FOLLOW: MOV BL,6
- CALL GET_CODE
- JC FOLLOWERS_END
- MOV FOLLOWERS[BP],AL
- OR AL,AL
- JZ LOOP_FOLLOW
- XOR DI,DI
-
- NEXT_FOLLOW2: MOV BL,8
- CALL GET_CODE
- JC FOLLOWERS_END
- INC DI
- MOV FOLLOWERS[BP+DI],AL
- MOV AX,DI
- CMP AL,FOLLOWERS[BP]
- JB NEXT_FOLLOW2
-
- LOOP_FOLLOW: SUB BP,SIZE FOLLOWER
- JNC NEXT_FOLLOW
- CLC
-
- FOLLOWERS_END: RET
-
- ;----------------------------------------------;
- ; INPUT: AL=Char; OUTPUT: CF=1 if failed.
-
- DLE = 144
-
- STATE_ZERO: CMP AL,DLE
- JZ CHANGE_STATE
- CALL STORE_CHAR
- RET
-
- CHANGE_STATE: MOV STATE,OFFSET STATE_ONE
- CLC
- ZERO_END: RET
-
- ;----------------------------------------------;
- ; INPUT: AL=Char; OUTPUT: CF=1 if failed.
-
- SAVE_REDUCE DW ?
- EXPAND_LEN DW ?
-
- STATE_ONE: OR AL,AL
- JZ WRITE_DLE
- MOV SAVE_REDUCE,AX
- AND AX,REDUCE_L
- MOV EXPAND_LEN,AX
- MOV BX,OFFSET STATE_THREE
- CMP AX,REDUCE_F
- JNZ SAVE_STATE
- MOV BX,OFFSET STATE_TWO
- SAVE_STATE: MOV STATE,BX
- CLC
- RET
-
- WRITE_DLE: MOV AL,DLE
- CALL STORE_CHAR
- MOV STATE,OFFSET STATE_ZERO
- RET
-
- ;----------------------------------------------;
- ; INPUT: AL=Char; OUTPUT: CF=1 if failed.
-
- STATE_TWO: ADD EXPAND_LEN,AX
- MOV STATE,OFFSET STATE_THREE
- CLC
- RET
-
- ;----------------------------------------------;
- ; INPUT: AL=Char; OUTPUT: CF=1 if failed.
-
- STATE_THREE: MOV BX,SAVE_REDUCE
- MOV CL,REDUCE_D1
- SHR BX,CL
- AND BX,REDUCE_D2
- MOV CL,8
- SHL BX,CL
- ADD BX,AX
- INC BX
-
- MOV CX,EXPAND_LEN
- INC CX
- INC CX
- INC CX
- CALL BACKWARDS
- MOV STATE,OFFSET STATE_ZERO
- RET
-
- ;**********************************************;
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- EXPLODE_MSG DB "Exploding $"
-
- DISTANCE DW ?
- DICT_BITS DB ?
- MIN_MATCH_LEN DW ?
- WRITE_FLAG DB ?
-
- EXPLODE: MOV DX,OFFSET EXPLODE_MSG
- CALL PRINT_STRING
- CALL WRITE_FILENAME
-
- MOV WRITE_FLAG,0
- CALL LOAD_TREES
- JC LILLY_EXIT4
-
- EXPLODE_SPIN: CALL SPINNER
-
- NEXT_EXPLODE: INC SPIN_CNT
- JZ EXPLODE_SPIN
-
- MOV BL,1
- CALL GET_CODE
- JC LILLY_EXIT3
- OR AX,AX
- JZ SLIDING_DICT
- TEST COMPRESS_FLAG,100B
- JZ GET_A_CODE
- MOV BP,OFFSET LIT_TREE
- CALL READ_TREE
- JC LILLY_EXIT3
- JMP SHORT STORE_BYTE
-
- GET_A_CODE: MOV BL,8
- CALL GET_CODE
- JC LILLY_EXIT3
-
- STORE_BYTE: CALL STORE_CHAR
- JNC NEXT_EXPLODE
- JMP EXPLODE_END2
-
- LILLY_EXIT3: CLC
- LILLY_EXIT4: JMP EXPLODE_END2
-
-
- SLIDING_DICT: MOV BL,DICT_BITS
- CALL GET_CODE
- JC EXPLODE_END2
- MOV DISTANCE,AX
-
- MOV BP,OFFSET DISTANCE_TREE
- CALL READ_TREE
- JC EXPLODE_END2
- MOV CL,DICT_BITS
- SHL AX,CL
- OR DISTANCE,AX
-
- MOV BP,OFFSET LENGTH_TREE
- CALL READ_TREE
- JC EXPLODE_END2
- MOV DI,AX
- ADD AX,MIN_MATCH_LEN
- CMP DI,63
- JNZ DO_BACKWARDS
- MOV DI,AX
- MOV BL,8
- CALL GET_CODE
- JC EXPLODE_END
- ADD AX,DI
-
-
- DO_BACKWARDS: MOV CX,AX ;Length
- MOV BX,DISTANCE
- INC BX
- CALL BACKWARDS
- JNC NEXT_EXPLODE
- JMP SHORT EXPLODE_END2
-
- EXPLODE_END: CLC
- EXPLODE_END2: RET
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- LOAD_TREES: MOV AL,COMPRESS_FLAG
- MOV AH,7
- TEST AL,10B
- JNZ STORE_DICT
- DEC AH
- STORE_DICT: MOV DICT_BITS,AH
-
- MOV MIN_MATCH_LEN,2
- TEST AL,100B
- JZ OTHER_TREES
-
- MOV MIN_MATCH_LEN,3
- MOV BP,OFFSET LIT_TREE
- MOV WORD PTR TREE_ENTRIES[BP],256
- CALL LOAD_TREE
- JC LOAD_TR_END
-
- OTHER_TREES: MOV BP,OFFSET LENGTH_TREE
- MOV WORD PTR TREE_ENTRIES[BP],64
- CALL LOAD_TREE
- JC LOAD_TR_END
-
- MOV BP,OFFSET DISTANCE_TREE
- MOV WORD PTR TREE_ENTRIES[BP],64
- CALL LOAD_TREE
-
- LOAD_TR_END: RET
-
- ;----------------------------------------------;
- ; INPUT: BP=Tree index. OUTPUT: CF=1 if failed.
-
- LOAD_TREE: CALL READ_LEN
- JC LOAD_TREE_END
- CALL SORT_LEN
- CALL MAKE_TREE
- CALL REVERSE_BITS
- CLC
- LOAD_TREE_END: RET
-
- ;----------------------------------------------;
- ; INPUT: BP=Tree index. OUTPUT: CF=1 if failed.
-
- TREE_BYTES DB ?
-
- READ_LEN: MOV BL,8
- CALL GET_CODE
- JC READ_LEN_END
- INC AX
- MOV TREE_BYTES,AL
- XOR DI,DI
-
- NEXT_LEN: MOV BL,8
- CALL GET_CODE
- JC READ_LEN_END
- MOV AH,AL
- MOV CL,4
- SHR AH,CL
- AND AL,0FH
- INC AH
- INC AL
-
- NEXT_LEN2: MOV CX,DI
- MOV SI,DI
- SHL SI,1
- SHL SI,1
- MOV BIT_LENGTH[BP+SI],AL
- MOV VALUE[BP+SI],CL
- INC DI
- DEC AH
- JNZ NEXT_LEN2
-
- DEC TREE_BYTES
- JNZ NEXT_LEN
- CLC
-
- READ_LEN_END: RET
-
- ;----------------------------------------------;
- ; INPUT: BP=Tree index.
-
- SORT_LEN: MOV AX,CS
- MOV ES,AX
- MOV AX,SIZE SF_TREE
- MUL WORD PTR TREE_ENTRIES[BP]
- ADD AX,BP
- MOV CX,BP
-
- NEXT_SORT: MOV BX,CX
- MOV DX,CX
- ADD DX,SIZE SF_TREE
- CMP DX,AX
- JAE SORT_END
-
- NEXT_SORT2: MOV SI,BX
- MOV DI,DX
- CMPSB
- JB LOOP_SORT
- JA SORT_IT
-
- CMPSB
- JBE LOOP_SORT
- DEC SI
- DEC DI
-
- SORT_IT: DEC SI
- DEC DI
- PUSH [DI]
- MOVSW
- POP [BX]
-
- LOOP_SORT: ADD DX,SIZE SF_TREE
- CMP DX,AX
- JB NEXT_SORT2
- ADD CX,SIZE SF_TREE
- JMP NEXT_SORT
-
- SORT_END: RET
-
- ;----------------------------------------------;
- ; INPUT: BP=Tree index.
-
- MAKE_TREE: MOV AX,SIZE SF_TREE
- MUL WORD PTR TREE_ENTRIES[BP]
- ADD AX,BP
- MOV SI,AX
- XOR AX,AX ;Code
- XOR BL,BL ;Last bit length
- XOR DI,DI ;Code increment
-
- NEXT_MAKE: SUB SI,SIZE SF_TREE
- CMP SI,BP
- JB MAKE_END
- ADD AX,DI
- MOV TREE_CODE[SI],AX
- MOV BH,BIT_LENGTH[SI]
- CMP BH,BL
- JZ NEXT_MAKE
-
- MOV BL,BH
- MOV CL,16
- SUB CL,BL
- MOV DI,1
- SHL DI,CL
- JMP NEXT_MAKE
-
- MAKE_END: RET
-
- ;----------------------------------------------;
- ; INPUT: BP=Tree index.
-
- REVERSE_BITS: MOV DX,TREE_ENTRIES[BP]
- MOV SI,BP
- NEXT_REV: INC SI
- INC SI ;Code
- LODSW
- XOR BX,BX
- MOV CX,16
- NEXT_REV2: SHR AX,1
- RCL BX,1
- LOOP NEXT_REV2
- MOV [SI-2],BX
- DEC DX
- JNZ NEXT_REV
- RET
-
- ;----------------------------------------------;
- ; INPUT: BP=Tree index. OUTPUT: AX=code; CF=1 if failed.
-
- INDEX DW ?
- BITS DB ?
-
- READ_TREE: XOR DI,DI ;Code
- XOR DX,DX ;Bit length
- XOR CL,CL ;Bits
- NEXT_READ_T: MOV BITS,CL
- MOV BL,1
- CALL GET_CODE
- JC READ_T_END2
- MOV CL,BITS
- SHL AX,CL
- OR DI,AX
- INC CL
- MOV SI,DX
-
- NEXT_READ_T2: SHL SI,1
- SHL SI,1
- CMP BIT_LENGTH[BP+SI],CL
- JA NEXT_READ_T
- JZ NEXT_READ_T3
- INC DX
- MOV SI,DX
- CMP SI,TREE_ENTRIES[BP]
- JB NEXT_READ_T2
- JMP TREE_ERROR
-
- NEXT_READ_T3: CMP TREE_CODE[BP+SI],DI
- JNZ LOOP_TREE
- MOV AL,VALUE[BP+SI]
- XOR AH,AH
- JMP SHORT READ_T_END
-
- LOOP_TREE: INC DX
- MOV SI,DX
- CMP SI,TREE_ENTRIES[BP]
- JAE TREE_ERROR
- SHL SI,1
- SHL SI,1
- CMP BIT_LENGTH[BP+SI],CL
- JZ NEXT_READ_T3
- JMP NEXT_READ_T
-
- TREE_ERROR: STC
- JMP SHORT READ_T_END2
-
- READ_T_END: CLC
- READ_T_END2: RET
-
- ;----------------------------------------------;
- ; INPUT: CX=Length; BX=Distance; OUTPUT: CF=1 if failed.
-
- BACKWARDS: MOV ES,WRITE_SEG
- MOV SI,WRITE_PTR
- SUB SI,BX
- JNC NEXT_BACK
- CMP WRITE_FLAG,1
- JZ END_BUFF
-
- NEXT_NULL: OR SI,SI
- JZ NEXT_BACK
- XOR AL,AL
- CALL STORE_CHAR
- JC BACKWARDS_END
- INC SI
- LOOP NEXT_NULL
- JMP BACKWARDS_END
-
- END_BUFF: ADD SI,WRITE_SIZE
- NEXT_BACK: MOV AL,ES:[SI]
- CALL STORE_CHAR
- JC BACKWARDS_END
- INC SI
- CMP SI,WRITE_SIZE
- JNZ LOOP_BACK
- XOR SI,SI
- LOOP_BACK: LOOP NEXT_BACK
- CLC
- BACKWARDS_END: RET
-
- ;**********************************************;
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- BASE_CHAR DB ?
- PREV_CODE DW ?
- SAVE_CODE DW ?
-
- UNSHRINK_MSG DB "Unshrinking $"
-
- UNSHRINK: MOV DX,OFFSET UNSHRINK_MSG
- CALL PRINT_STRING
- CALL WRITE_FILENAME
-
- CALL INIT_UNSHRINK
-
- MOV BL,CODE_BITS
- CALL GET_CODE
- JC LILLY_EXIT
- MOV PREV_CODE,AX
- MOV BASE_CHAR,AL
- CALL STORE_CHAR
- JC LILLY_EXIT2
-
- UNSHRINK_SPIN: CALL SPINNER
-
- NEXT_UNSHRINK: INC SPIN_CNT
- JZ UNSHRINK_SPIN
-
- MOV BL,CODE_BITS
- CALL GET_CODE
- JC LILLY_EXIT
- MOV SAVE_CODE,AX
- XOR CX,CX ;String counter.
-
- CMP AX,SPECIAL_CODE
- JB STORE_UNSHRUNK
- JA CK_ERROR
-
- MOV BL,CODE_BITS
- CALL GET_CODE
- JC LILLY_EXIT
- DEC AX
- JNZ CK_CLEAR
- INC CODE_BITS
- JMP NEXT_UNSHRINK
-
- CK_CLEAR: DEC AX
- STC
- JNZ LILLY_EXIT2
- CALL CLEAR
- JMP NEXT_UNSHRINK
-
- LILLY_EXIT: CLC
- LILLY_EXIT2: JMP UNSHRINK_END
-
- CK_ERROR: CMP AX,TRIE_SIZE
- JA ERROR
-
- MOV BX,AX
- SHL BX,1
- CMP WORD PTR PREFIX[BX],FREE
- JNZ FIND_STRING2
- PUSH WORD PTR BASE_CHAR
- INC CX
-
- MOV BX,PREV_CODE
- CMP BX,FIRST_FREE
- JB GOT_UNSHRUNK
-
- FIND_STRING: SHL BX,1
- FIND_STRING2: PUSH SUFFIX[BX]
- INC CX
- MOV BX,PREFIX[BX]
- CMP BX,FIRST_FREE
- JAE FIND_STRING
-
- GOT_UNSHRUNK: MOV AL,BL
- STORE_UNSHRUNK:MOV BASE_CHAR,AL
-
- CALL STORE_CHAR
- JC UNSHRINK_END
- JCXZ ADD_CODE
- NEXT_STORE: POP AX
- CALL STORE_CHAR
- JC UNSHRINK_END
- LOOP NEXT_STORE
-
- ADD_CODE: MOV DI,FREE_NODE
- MOV AL,BASE_CHAR
- MOV SUFFIX[DI],AL
- MOV AX,PREV_CODE
- MOV PREFIX[DI],AX
-
- NEXT_FREE: INC DI
- INC DI
- CMP DI,TRIE_SIZE * 2
- JA ERROR
- CMP WORD PTR PREFIX[DI],FREE
- JNZ NEXT_FREE
- MOV FREE_NODE,DI
-
- MOV AX,SAVE_CODE
- MOV PREV_CODE,AX
- JMP NEXT_UNSHRINK
-
- ERROR: STC
-
- UNSHRINK_END: RET
-
- ;----------------------------------------------;
- INIT_UNSHRINK: PUSH CS
- POP ES
- MOV DI,OFFSET PREFIX
- MOV AX,FREE
- MOV CX,TRIE_SIZE
- REP STOSW
-
- MOV FREE_NODE,FIRST_FREE * 2
- MOV CODE_BITS,MIN_CODE_SIZE
- RET
-
- ;----------------------------------------------;
- ; INPUT: BITS_LEFT; BL=CODE_BITS; OUTPUT: AX=code; CF=1 if EOF or failed.
-
- GET_CODE: MOV CL,BL
- XOR AX,AX
- MOV BH,BITS_LEFT
- OR BH,BH
- JZ GET_BITS
- MOV CH,SAVE_BYTE
-
- NEXT_SHIFT2: SHR CH,1
- RCR AX,1
- DEC BL
- JZ GOT_CODE
- DEC BH
- JNZ NEXT_SHIFT2
-
- GET_BITS: MOV SI,READ_PTR
- CMP SI,BYTES_READ
- JZ GET_BYTE
- MOV ES,READ_SEG
- MOV CH,ES:[SI]
- INC READ_PTR
- MOV BH,8
- JMP NEXT_SHIFT2
-
- GET_BYTE: CALL READ_ZIP
- JNC GET_BITS
- JMP SHORT GET_CODE_END
-
- GOT_CODE: DEC BH
- MOV SAVE_BYTE,CH
- MOV BITS_LEFT,BH
- NEG CL
- ADD CL,16
- SHR AX,CL
- CLC
- GET_CODE_END: RET
-
- ;----------------------------------------------;
- CLEAR:
- ;Mark all nodes as potentially unused.
- MOV DX,FREE_NODE
- MOV AX,8000H
- MOV CX,FIRST_FREE * 2
- MOV SI,CX
- NEXT_MARK: CMP SI,DX
- JZ CK_REF
- OR PREFIX[SI],AX
- INC SI
- INC SI
- JMP NEXT_MARK
-
- ;Unmark those that are used by other nodes
- CK_REF: MOV SI,CX
- NEXT_REF: CMP SI,DX
- JZ DO_CLEAR
- MOV AX,PREFIX[SI]
- INC SI
- INC SI
- AND AX,7FFFH
- CMP AX,FIRST_FREE
- JB NEXT_REF
- MOV DI,AX
- SHL DI,1
- AND PREFIX[DI],7FFFH
- JMP NEXT_REF
-
- ;Clear the ones that are still marked
- DO_CLEAR: MOV SI,CX
- MOV AX,FREE
- JMP SHORT NEXT_CLEAR2
- NEXT_CLEAR: INC SI
- INC SI
- NEXT_CLEAR2: CMP SI,DX
- JZ FIND_FREE
- MOV DI,PREFIX[SI]
- AND DI,8000H
- JZ NEXT_CLEAR
- MOV PREFIX[SI],AX
- JMP NEXT_CLEAR
-
- ;Find first free node
- FIND_FREE: MOV SI,FIRST_FREE * 2
- JMP SHORT NEXT_FREE3
- NEXT_FREE2: INC SI
- INC SI
- NEXT_FREE3: CMP PREFIX[SI],AX
- JNZ NEXT_FREE2
- MOV FREE_NODE,SI
-
- RET
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed or EOF.
-
- BYTES_TO_READ DW ?,?
- READ_PTR DW ?
- BYTES_READ DW ?
- READ_HANDLE DW ?
-
- READ_ZIP: PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- MOV READ_PTR,0
-
- MOV CX,READ_SIZE
- CMP BYTES_TO_READ[2],0
- JNZ READ_IT
- MOV AX,BYTES_TO_READ[0]
- OR AX,AX
- STC
- JZ READ_ZIP_END
- CMP CX,AX
- JBE READ_IT
- MOV CX,AX
-
- READ_IT: PUSH DS
- MOV BX,READ_HANDLE
- XOR DX,DX
- MOV DS,READ_SEG
- MOV AH,3FH
- INT 21H
- POP DS
- JC READ_ZIP_END
-
- CMP AX,CX
- STC
- JNZ READ_ZIP_END
- MOV BYTES_READ,AX
- SUB BYTES_TO_READ[0],AX
- SBB BYTES_TO_READ[2],0
- CLC
-
- READ_ZIP_END: POP DX
- POP CX
- POP BX
- POP AX
- RET
-
- ;----------------------------------------------;
- ; INPUT: AL=Char; OUTPUT: CF=1 if failed.
-
- WRITE_PTR DW ?
-
- STORE_CHAR: MOV ES,WRITE_SEG
- MOV DI,WRITE_PTR
- STOSB
- INC WRITE_PTR
-
- MOV BX,RUNNING_CRC_32[0]
- MOV DX,RUNNING_CRC_32[2]
-
- XOR AL,BL
- XOR AH,AH
- MOV BP,AX
- SHL BP,1
- SHL BP,1
-
- MOV AL,8
- NEXT_SHIFT: SAR DX,1 ;DX:BX
- RCR BX,1
- DEC AL
- JNZ NEXT_SHIFT
- AND DX,00FFH
-
- XOR BX,WORD PTR CRC_32_TABLE[BP]
- XOR DX,WORD PTR CRC_32_TABLE[BP+2]
-
- MOV RUNNING_CRC_32[0],BX
- MOV RUNNING_CRC_32[2],DX
-
- CMP DI,WRITE_SIZE
- CLC
- JNZ STORE_END
- CALL WRITE
- STORE_END: RET
-
- ;----------------------------------------------;
- ; OUTPUT: CF=1 if failed.
-
- WRITE_HANDLE DW ?
-
- WRITE: PUSH CX
- MOV CX,WRITE_PTR
- OR CX,CX
- JZ WRITE_END
- MOV BX,WRITE_HANDLE
- XOR DX,DX
- PUSH DS
- MOV DS,WRITE_SEG
- MOV AH,40H
- INT 21H
- POP DS
- MOV WRITE_PTR,0
- MOV WRITE_FLAG,1
-
- WRITE_END: POP CX
- RET
-
- ;----------------------------------------------;
- WRITE_FILENAME:MOV DX,OFFSET DIR_NAME
- MOV SI,END_FILENAME
- PUSH [SI]
- MOV BYTE PTR [SI],"$"
- CALL PRINT_STRING
- POP [SI]
-
- MOV DL,SPACE
- MOV AH,2
- INT 21H
- RET
-
- ;----------------------------------------------;
- WRITE_CRLF: MOV DX,OFFSET CR_LF
- JMP SHORT NEW_LINE
-
- WRITE_CRLFLF: MOV DX,OFFSET CR_LF_LF
- NEW_LINE: CALL PRINT_STRING
- RET
-
- ;----------------------------------------------;
- PRINT_STRING: MOV AH,9 ;Print string via DOS.
- INT 21H
- RET
-
- ;----------------------------------------------;
- SPINNER: MOV SI,SPIN_INDEX
- SUB SI,1
- JNC STORE_SPIN
- MOV SI,2
- STORE_SPIN: MOV SPIN_INDEX,SI
- MOV AL,SPINNERS[SI]
-
- SPIN_IT: XOR BH,BH
- MOV CX,1
- MOV BL,ATTRIBUTE
- MOV AH,9
- INT 10H
- RET
-
- ;----------------------------------------------;
-
- CRC_32_TABLE LABEL DWORD
- DD 000000000h, 077073096h, 0EE0E612Ch, 0990951BAh, 0076DC419h, 0706AF48Fh, 0E963A535h, 09E6495A3h
- DD 00EDB8832h, 079DCB8A4h, 0E0D5E91Eh, 097D2D988h, 009B64C2Bh, 07EB17CBDh, 0E7B82D07h, 090BF1D91h
- DD 01DB71064h, 06AB020F2h, 0F3B97148h, 084BE41DEh, 01ADAD47Dh, 06DDDE4EBh, 0F4D4B551h, 083D385C7h
- DD 0136C9856h, 0646BA8C0h, 0FD62F97Ah, 08A65C9ECh, 014015C4Fh, 063066CD9h, 0FA0F3D63h, 08D080DF5h
- DD 03B6E20C8h, 04C69105Eh, 0D56041E4h, 0A2677172h, 03C03E4D1h, 04B04D447h, 0D20D85FDh, 0A50AB56Bh
- DD 035B5A8FAh, 042B2986Ch, 0DBBBC9D6h, 0ACBCF940h, 032D86CE3h, 045DF5C75h, 0DCD60DCFh, 0ABD13D59h
- DD 026D930ACh, 051DE003Ah, 0C8D75180h, 0BFD06116h, 021B4F4B5h, 056B3C423h, 0CFBA9599h, 0B8BDA50Fh
- DD 02802B89Eh, 05F058808h, 0C60CD9B2h, 0B10BE924h, 02F6F7C87h, 058684C11h, 0C1611DABh, 0B6662D3Dh
- DD 076DC4190h, 001DB7106h, 098D220BCh, 0EFD5102Ah, 071B18589h, 006B6B51Fh, 09FBFE4A5h, 0E8B8D433h
- DD 07807C9A2h, 00F00F934h, 09609A88Eh, 0E10E9818h, 07F6A0DBBh, 0086D3D2Dh, 091646C97h, 0E6635C01h
- DD 06B6B51F4h, 01C6C6162h, 0856530D8h, 0F262004Eh, 06C0695EDh, 01B01A57Bh, 08208F4C1h, 0F50FC457h
- DD 065B0D9C6h, 012B7E950h, 08BBEB8EAh, 0FCB9887Ch, 062DD1DDFh, 015DA2D49h, 08CD37CF3h, 0FBD44C65h
- DD 04DB26158h, 03AB551CEh, 0A3BC0074h, 0D4BB30E2h, 04ADFA541h, 03DD895D7h, 0A4D1C46Dh, 0D3D6F4FBh
- DD 04369E96Ah, 0346ED9FCh, 0AD678846h, 0DA60B8D0h, 044042D73h, 033031DE5h, 0AA0A4C5Fh, 0DD0D7CC9h
- DD 05005713Ch, 0270241AAh, 0BE0B1010h, 0C90C2086h, 05768B525h, 0206F85B3h, 0B966D409h, 0CE61E49Fh
- DD 05EDEF90Eh, 029D9C998h, 0B0D09822h, 0C7D7A8B4h, 059B33D17h, 02EB40D81h, 0B7BD5C3Bh, 0C0BA6CADh
- DD 0EDB88320h, 09ABFB3B6h, 003B6E20Ch, 074B1D29Ah, 0EAD54739h, 09DD277AFh, 004DB2615h, 073DC1683h
- DD 0E3630B12h, 094643B84h, 00D6D6A3Eh, 07A6A5AA8h, 0E40ECF0Bh, 09309FF9Dh, 00A00AE27h, 07D079EB1h
- DD 0F00F9344h, 08708A3D2h, 01E01F268h, 06906C2FEh, 0F762575Dh, 0806567CBh, 0196C3671h, 06E6B06E7h
- DD 0FED41B76h, 089D32BE0h, 010DA7A5Ah, 067DD4ACCh, 0F9B9DF6Fh, 08EBEEFF9h, 017B7BE43h, 060B08ED5h
- DD 0D6D6A3E8h, 0A1D1937Eh, 038D8C2C4h, 04FDFF252h, 0D1BB67F1h, 0A6BC5767h, 03FB506DDh, 048B2364Bh
- DD 0D80D2BDAh, 0AF0A1B4Ch, 036034AF6h, 041047A60h, 0DF60EFC3h, 0A867DF55h, 0316E8EEFh, 04669BE79h
- DD 0CB61B38Ch, 0BC66831Ah, 0256FD2A0h, 05268E236h, 0CC0C7795h, 0BB0B4703h, 0220216B9h, 05505262Fh
- DD 0C5BA3BBEh, 0B2BD0B28h, 02BB45A92h, 05CB36A04h, 0C2D7FFA7h, 0B5D0CF31h, 02CD99E8Bh, 05BDEAE1Dh
- DD 09B64C2B0h, 0EC63F226h, 0756AA39Ch, 0026D930Ah, 09C0906A9h, 0EB0E363Fh, 072076785h, 005005713h
- DD 095BF4A82h, 0E2B87A14h, 07BB12BAEh, 00CB61B38h, 092D28E9Bh, 0E5D5BE0Dh, 07CDCEFB7h, 00BDBDF21h
- DD 086D3D2D4h, 0F1D4E242h, 068DDB3F8h, 01FDA836Eh, 081BE16CDh, 0F6B9265Bh, 06FB077E1h, 018B74777h
- DD 088085AE6h, 0FF0F6A70h, 066063BCAh, 011010B5Ch, 08F659EFFh, 0F862AE69h, 0616BFFD3h, 0166CCF45h
- DD 0A00AE278h, 0D70DD2EEh, 04E048354h, 03903B3C2h, 0A7672661h, 0D06016F7h, 04969474Dh, 03E6E77DBh
- DD 0AED16A4Ah, 0D9D65ADCh, 040DF0B66h, 037D83BF0h, 0A9BCAE53h, 0DEBB9EC5h, 047B2CF7Fh, 030B5FFE9h
- DD 0BDBDF21Ch, 0CABAC28Ah, 053B39330h, 024B4A3A6h, 0BAD03605h, 0CDD70693h, 054DE5729h, 023D967BFh
- DD 0B3667A2Eh, 0C4614AB8h, 05D681B02h, 02A6F2B94h, 0B40BBE37h, 0C30C8EA1h, 05A05DF1Bh, 02D02EF8Dh
-
- EVEN
- STACK_POINTER = $ + LOCAL_STACK + (TRIE_SIZE * 2)
- PREFIX = OFFSET STACK_POINTER
- SUFFIX = OFFSET PREFIX + PREFIX_SIZE
-
- LENGTH_TREE = OFFSET STACK_POINTER + 2
- DISTANCE_TREE = OFFSET LENGTH_TREE + LEN_TREE_SIZE + 2
- LIT_TREE = OFFSET DISTANCE_TREE + DIST_TREE_SIZE + 2
-
- FOLLOWERS = OFFSET STACK_POINTER
-
- _TEXT ENDS
- END START