0001 ;=============================================================== 0002 ; 0003 ; UNPACK input-ref output-ref 0004 ; 0005 ; Unpacks an ASCII file that had been packed with the PACK 0006 ; command. The fileref syntax is identical to PACK, i.e. 0007 ; 0008 ; input-ref :: [x:] inputname [.typ] 0009 ; 0010 ; If the drivecode x: is omitted the default drive is used. An 0011 ; input filename is required. A filetype is optional (or, to 0012 ; be precise, a filetype of 3 blanks is allowed). 0013 ; 0014 ; output-ref :: [y:] [outputname] [.typ] 0015 ; 0016 ; Each omitted part of the output fileref is supplied from the 0017 ; input-ref. Thus the default drive is the input drive, the 0018 ; default name is the input name, and the default type is the 0019 ; input type. If all are omitted, the output file replaces the 0020 ; input file. 0021 ; ***************************************************** 0022 ; * This program was originally published in * 0023 ; * A PROGRAMMER'S NOTEBOOK * 0024 ; * Utilities for CP/M-80 * 0025 ; * by David E. Cortesi * 0026 ; * Copyright (C) Reston Publishing Company Inc. 1983 * 0027 ; ***************************************************** 0028 *=============================================================== 0029 MACLIB CPMEQU 0030 MACLIB PROG 0031 PROLOG 0032 ;=============================================================== 0033 ; Equates for compression byte values: 0034 CopyThis equ 0EAh ; prefix for data > 127 0035 EndLine equ 0E8h ; stands for CR, LF 0036 EndLineTab equ 0E9h ; stands for CR, LF, TAB 0037 MaskByte1 equ 0Fh ; mask for first compressed byte 0038 MaskByte2 equ 07h ; ..and for second. 0039 ;=============================================================== 0040 ; Table used for fast vectoring in the Case construction. Each 0041 ; of 256 entries is the offset from CaseTop to the case label 0042 ; where the corresponding byte is handled. 0043 Table ds 256 0044 EndTable equ $ 0045 org Table 0046 $-PRINT 0047 ; fill from 00..7F with vectors to Case007F. 0048 rept 07Fh-000h+1 0049 db Case007F-CaseTop 0050 endm 0051 ; fill from 80..E7 with vectors to Case80E7. 0052 rept 0E7h-080h+1 0053 db Case80E7-CaseTop 0054 endm 0055 ; fill the rest with vectors to CaseUGH 0056 rept 0FFh-0E8h+1 0057 db CaseUGH-CaseTop 0058 endm 0059 ; plug in the vectors for EndLine/Tab and CopyThis 0060 org Table+EndLine 0061 db CaseEndLine-CaseTop 0062 org Table+EndLineTab 0063 db CaseEndLineTab-CaseTop 0064 org Table+CopyThis 0065 db CaseCopyThis-CaseTop 0066 org EndTable 0067 $+PRINT 0068 ;=============================================================== 0069 ; List of compress-characters, indexed by masked compress byte 0070 List: db ' etaoinshrdlu' 0071 ;=============================================================== 0072 ; Utility I/O variables... 0073 ; #include utilio.inc,IOVars 0074 MsgBadByte db 'Impossible byte in input file.$' 0075 ;=============================================================== 0076 ; the main program -- initialization 0077 Main: 0078 call SetUpInput ; open the input file 0079 lxi b,InFCB ; BC-->default fileref 0080 lxi d,OBspace ; DE-->start of buffer space 0081 ; prolog sets HL-->end of buffer space 0082 call SetUpOutput ; prepare the output stuff 0083 ;=============================================================== 0084 ; the main program -- main loop 0085 ; 0086 call Shift ; set up the B, C text window 0087 call Shift 0088 MainWhile: 0089 mov a,b ; while (B<>EOF)... 0090 cpi CpmEof 0091 jz MainEnd 0092 ; Case (B) of... 0093 mvi d,0 ; D will be zero throughout 0094 mov e,b 0095 lxi h,Table 0096 dad d ; HL-->case vector byte 0097 mov e,m 0098 lxi h,CaseTop 0099 dad d ; HL-->code of selected case 0100 pchl ; ..go to it. 0101 CaseTop: 0102 Case007F: 0103 jmp CaseEnd ; regular byte, do nothing 0104 ; 0105 Case80E7: 0106 rar ; shift A (=B) right 3 0107 rar ; (normally we'd have to 0108 rar ; worry about the carry flag, 0109 ani MaskByte1 ; but this masks any garbage) 0110 mov e,a ; DE=offset of byte in list 0111 lxi h,List 0112 dad d ; HL-->first output byte 0113 mov a,m 0114 call PutChar 0115 mov a,b 0116 ani MaskByte2 0117 mov e,a ; DE=offset of second byte 0118 lxi h,List 0119 dad d ; HL-->second compressed byte 0120 mov b,m 0121 jmp CaseEnd 0122 ; 0123 CaseEndLine: 0124 mvi a,AsciiCR 0125 call PutChar 0126 mvi b,AsciiLF 0127 jmp CaseEnd 0128 ; 0129 CaseEndLineTab: 0130 mvi a,AsciiCR 0131 call PutChar 0132 mvi a,AsciiLF 0133 call PutChar 0134 mvi b,AsciiTAB 0135 jmp CaseEnd 0136 ; 0137 CaseCopyThis: 0138 call Shift 0139 jmp CaseEnd 0140 ; 0141 CaseUGH: 0142 ABORT MsgBadByte 0143 ; 0144 CaseEnd: 0145 call Shout ; write B, get another 0146 jmp MainWhile ; ..end while 0147 ; 0148 MainEnd: 0149 call FinishOutput ; complete output file 0150 ret ; end main. 0151 ;=============================================================== 0152 ; the included I/O subroutines -- GetChar, PutChar, DumpOutput 0153 ; #include utilio.inc,IOSubs 0154 ;=============================================================== 0155 ; the file preparation code -- SetUpInput, SetUp-, FinishOutput 0156 ; #include utilio.inc,IOSetup 0157 ;=============================================================== 0158 ; The end of the program, and the start of the buffer space. 0159 ; The technique of using all storage for buffer, used here, is 0160 ; a liability in MP/M. There, the entire output buffer should 0161 ; be defined in the program or obtained with XDOS service 129. 0162 ; 0163 OBspace equ $ 0164 END * CROSS-REFERENCE * def. val. symbol and uses * ---- 000D ASCIICR MVI-124 -130 * ---- 000A ASCIILF MVI-126 -132 * ---- 0009 ASCIITAB MVI-134 * 0102 03FA CASE007F DB-49 * 0105 03FD CASE80E7 DB-53 * 0137 0430 CASECOPYTHIS DB-65 * 0144 043E CASEEND JMP-103 -121 -127 -135 -139 * 0123 0417 CASEENDLINE DB-61 * 0129 0421 CASEENDLINETAB DB-63 * 0101 03FA CASETOP DB-49 -53 -57 -61 -63 -65 LXI-98 * 0141 0436 CASEUGH DB-57 * 0034 00EA COPYTHIS ORG-64 * ---- 001A CPMEOF CPI-90 * 0035 00E8 ENDLINE ORG-60 * 0036 00E9 ENDLINETAB ORG-62 * 0044 0256 ENDTABLE ORG-66 * ---- 0689 FINISHOUTPUT CALL-149 * ---- 0263 INFCB LXI-79 * 0070 0256 LIST LXI-111 -118 * 0077 03D5 MAIN * 0148 0444 MAINEND JZ-91 * 0088 03E7 MAINWHILE JMP-146 * 0037 000F MASKBYTE1 ANI-109 * 0038 0007 MASKBYTE2 ANI-116 * 0074 03B6 MSGBADBYTE ABORT-142 * 0163 06F7 OBSPACE LXI-80 * ---- 0485 PUTCHAR CALL-114 -125 -131 -133 * ---- 050F SETUPINPUT CALL-78 * ---- 05B5 SETUPOUTPUT CALL-82 * ---- 044C SHIFT CALL-86 -87 -138 * ---- 0448 SHOUT CALL-145 * 0043 0156 TABLE ORG-45 -60 -62 -64 LXI-95 * CENSUS OF OPCODE USAGE * * ABORT 1 ANI 2 CALL 11 * CPI 1 DAD 4 DB 8 * DS 1 END 1 ENDM 3 * EQU 7 JMP 6 JZ 1 * LXI 6 MACLIB 2 MOV 8 * MVI 6 ORG 5 PCHL 1 * PRINT 2 PROLOG 1 RAR 3 * REPT 3 RET 1