home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / mskermit.tar.gz / mskermit.tar / msbpcg.asm < prev    next >
Assembly Source File  |  1990-06-19  |  8KB  |  311 lines

  1. ; Written by Dan Norstedt, Stockholm, Sweden        Last edit 17-Feb-1990
  2. ;
  3. ; This program is placed in the public domain.
  4. ;
  5. ; Use this program to generate MSBPCT.COM for MS-DOS with the commands:
  6. ;
  7. ;   C>MASM MSBPCG;
  8. ;   C>LINK MSBPCG;
  9. ;   C>MSBPCG >MSBPCT.COM
  10. ;
  11. ; The generated MSBPCT.COM file is trick coded, and only contains
  12. ; printable 7-bit ASCII characters. Thus, it can be sent as text
  13. ; without modifications, just capture it to disk, trim off excess
  14. ; text, and execute it. It takes one input argument, the input file.
  15. ; If no valid file is given, a Usage: message is given.
  16. ;
  17. ; The program will decodes about 10Kbyte/sec on my AT hard disk.
  18. ;
  19. ; The loader and builder portions of this program may be useful for other
  20. ; programs, too.
  21.  
  22.     CODE    SEGMENT PUBLIC
  23.  
  24.     ASSUME    CS:CODE,DS:CODE
  25.  
  26.     ORG    100H
  27.  
  28. START:    JMP    GENCOM
  29.  
  30.     ORG    100H+72+1        ; Address where loader starts loading
  31.  
  32. CODARE:
  33.  
  34. ;----------------------- beginning of MSBPCT code area -----------------------
  35.  
  36. INBUF    EQU    ((Offset MSBEND-Offset START+1FFH) AND 0FF00H)
  37. INBSIZ    EQU    400H
  38. OUTBUF    EQU    INBUF+INBSIZ
  39.  
  40. ;    CLD            ; Already done in the loader
  41.     MOV    DX,Offset MEMTXT
  42.     CMP    SP,0FF00H    ; Enough memory?
  43.     JB    OUTMSG
  44.     MOV    SI,80H        ; Point at line length byte
  45.     XOR    AH,AH
  46.     LODSB            ; Get it
  47.     XCHG    AX,BX
  48.     MOV    Word Ptr [SI+BX],0 ; Clear end of command string
  49.     LEA    DX,[SI+1]
  50.     MOV    AX,3D00H    ; Try to open the file
  51.     INT    21H
  52.     MOV    DX,Offset USETXT ; Tell usage if we can't open input file
  53.     JNC    OPENOK
  54. OUTMSG:    MOV    AX,901H        ; Output error text
  55. EXIT:    PUSH    AX
  56.     INT    21H
  57.     POP    AX        ; Set up exit code
  58.     MOV    AH,4CH
  59.     INT    21H
  60. OPENOK:    XCHG    BX,AX        ; Save input handle
  61.     MOV    DX,Offset FILTXT ; Output header
  62.     MOV    AH,9
  63.     MOV    SI,OUTBUF    ; Temorary buffer for output filename
  64. RDMORE:    INT    21H
  65.     MOV    AH,3FH        ; Read a character
  66.     MOV    CX,1
  67.     MOV    DX,SI
  68.     INT    21H
  69. ERROR:    MOV    DX,Offset ERRTXT
  70.     JC    OUTMSG        ; Error if failure here
  71.     DEC    AX
  72.     JNZ    OUTMSG
  73.     LODSB
  74.     XCHG    AX,DX
  75.     MOV    AH,2        ; Prepare for output
  76.     CMP    DL,20H
  77.     JA    RDMORE        ; Printable character -> save and output
  78.     MOV    AH,3CH        ; Prepare for file create
  79.     XOR    CX,CX
  80.     MOV    [SI-1],CL    ; Make input filename buffer NUL terminated
  81.     MOV    DX,OUTBUF    ; Pointer to file name
  82.     MOV    DI,DX
  83.     INT    21H        ; Create output file
  84.     JC    ERROR
  85.     XCHG    AX,BX        ; Save file output file handle in BX
  86.     XCHG    AX,BP        ; Input file handle to BP
  87. READBU:    PUSH    DX        ; Save shift count (initial value in DL = 0)
  88.     MOV    DX,OUTBUF
  89.     MOV    CX,DI
  90.     SUB    CX,DX        ; Compute size of output buffer
  91.     JZ    NOWRIT        ; Zero, skip write
  92.     MOV    AH,40H        ; Write it out
  93.     INT    21H
  94.     JC    ERROR
  95.     SUB    AX,CX        ; Write failed?
  96.     JC    ERROR
  97. NOWRIT:    MOV    DI,DX        ; No, reset output buffer pointer
  98.     MOV    DX,INBUF    ; Load input buffer pointer
  99.     MOV    SI,DX        ; Set up for later use
  100.     MOV    CX,INBSIZ    ; Read one buffer of appropriate size
  101.     MOV    AH,3FH
  102.     XCHG    BX,BP        ; Swap input and output file handles
  103.     INT    21H
  104.     XCHG    BX,BP
  105.     JC    ERROR
  106.     XCHG    AX,CX
  107.     MOV    AX,3E00H    ; Load good close function code, just in case
  108.     JCXZ    EXIT        ; End of input file, do the good exit
  109.     POP    DX        ; Regain shift count (in DL)
  110. INLOOP:    LODSB            ; Get a character
  111.     SUB    AL,30H
  112.     JL    CHRDON        ; Junk, throw away
  113.     MOV    AH,DH        ; Good one, get old saved char to AH
  114.     MOV    DH,AL        ; Save current instead
  115.     CMP    AH,4EH        ; Old character flags expansion of NULs?
  116.     JZ    NULLS
  117.     SHL    AL,1        ; No merge low bits of old char with new char
  118.     SHL    AL,1
  119.     XCHG    CX,DX        ; Get current shift amount (0, 2, 4 or 6)
  120.     SHR    AX,CL        ; Do shift
  121.     XCHG    CX,DX
  122.     SUB    DL,2        ; Adjust for new shift factor,old = 0 -> skip?
  123.     JS    INLOOR        ; Yes, skip
  124.     STOSB            ; No, save result of shift operation
  125. INLOOR:    AND    DL,6        ; Adjust shift count if DL was = 0
  126.     JMP    Short CHRDON    ; End loop
  127. NULLS:    CBW            ; Expand NUL count
  128.     CWD            ; Reset shift count in DL and NULL flag in DH
  129.     PUSH    CX        ; Save input character left counter 
  130.     XCHG    AX,CX
  131.     MOV    AL,0
  132.     REP    STOSB        ; Store selected amount of NULs
  133.     POP    CX        ; Restore counter
  134. CHRDON:    LOOP    INLOOP        ; Loop for rest of input block
  135.     JMP    Short READBU    ; Try to read another buffer
  136.  
  137. USETXT    DB    'Usage: MSBPCT file.BOO$'
  138.  
  139. FILTXT    DB    'Unpacking to file: $'
  140.  
  141. ERRTXT    DB    'Error during file I/O$'
  142.  
  143. MEMTXT    DB    'Not enough memory$'
  144.  
  145. MSBEND:
  146.  
  147. ;-------------------------- end of MSBPCT code area --------------------------
  148.  
  149. CODEND:
  150.  
  151. ;-- Loader starts here; don't touch unless you REALLY know what's going on --
  152.  
  153. FIXUP    MACRO    LABL,OFFS,DAT,DA2,DAS
  154.     ORG    $+(OFFS)
  155. LABL    Label    Byte
  156.     IFNB    <DAS>
  157.      IFNB    <DA2>
  158.       DB     (((DAS) OR 65H)-((DAS) AND 65H)) AND 0FFH,0FFH-(DA2)
  159.       ORG     $-1
  160.      ELSE
  161.       DB     ((DAS)+65H) AND 0FFH
  162.      ENDIF
  163.     ELSE
  164.      DB    0FFH-((DAT) AND 0FFH)
  165.      IFNB    <DA2>
  166.       DB     0FFH-(DA2)
  167.       ORG     $-1
  168.      ENDIF
  169.     ENDIF
  170.     ORG    $-(OFFS)-1
  171.     ENDM
  172.  
  173. FIXBYT    MACRO    ADDR     ; Generate "XOR [BX+ADDR-0FFH],AL" with 8-bit offset
  174.     DB    30H,47H,(Offset ADDR-Offset LOADER+100H)-0FFH
  175.     ENDM
  176.  
  177. FIXBYH    MACRO    ADDR     ; Generate "XOR [BX+ADDR-0FFH],AH" with 8-bit offset
  178.     DB    30H,67H,(Offset ADDR-Offset LOADER+100H)-0FFH
  179.     ENDM
  180.  
  181. FIXWRD    MACRO    ADDR     ; Generate "XOR [BX+ADDR-0FFH],AX" with 8-bit offset
  182.     DB    31H,47H,(Offset ADDR-Offset LOADER+100H)-0FFH
  183.     ENDM
  184.  
  185. FIXSUB    MACRO    ADDR     ; Generate "SUB [BX+ADDR-0FFH],AL" with 8-bit offset
  186.     DB    28H,47H,(Offset ADDR-Offset LOADER+100H)-0FFH
  187.     ENDM
  188.  
  189. LOADER:    POP    AX
  190.     PUSH    AX
  191.     DEC    AX        ; Load AX with 0FFFFH
  192.     PUSH    AX        ; Now FF FF 00 00 on stack
  193.     INC    SP
  194.     POP    BX        ; Load BX with 00FF
  195.     FIXBYT    XORBXX        ; Fix up end of loader code
  196.     FIXBYT    XORB1
  197.     FIXBYT    XORB2
  198.     FIXWRD    XORW1
  199.     FIXWRD    XORW2
  200.     DAA            ; Load AL with 65H
  201.     FIXSUB    SUBB1
  202.     FIXSUB    SUBB2
  203.     JNZ    J0JMP        ; Break pipeline
  204. J0DST:    FIXBYH    XORB3
  205.     FIXSUB    SUBB3
  206.     FIXSUB    SUBB4
  207.     FIXWRD    XORX1
  208.  
  209. ; FC
  210.     CLD            ; Set LODSB direction
  211.     FIXUP    SUBB1,-1,,,0FCH
  212. ; 8D7749  LEA    SI,[BX+DATA-0FFH] ; Point at 100H+72
  213.     DB    8DH,77H,(Offset DATA-Offset LOADER+100H)-0FFH
  214.     FIXUP    XORB1,-3,8DH
  215. ; 56
  216.     PUSH    SI        ; Copy SI -> DI
  217. ; 5F
  218.     POP    DI
  219. ; 46
  220.     INC    SI
  221. J2DST:
  222. ; 2AC2
  223.     SUB    AL,DL        ; Compute real code/data byte
  224. ; AA
  225.     STOSB            ; Save it
  226.     FIXUP    XORW1,-2,0C2H,0AAH
  227. J1DST:
  228. J3DST:
  229. ; AC
  230.     LODSB            ; Get an encoded data byte
  231.     FIXUP    XORB2,-1,0ACH
  232. ; 40
  233.     INC    AX
  234. ; 3C31
  235.     CMP    AL,31H        ; Printable and >= '0'?
  236. ; 7CFA
  237.     JL    J1DST
  238. J1SRC:    FIXUP    SUBB2,-1,,,J1DST-J1SRC
  239. ; 2C35
  240.     SUB    AL,'4'+1    ; Yes, '0'-'3' (or '4' = exit code) ?
  241. ; 77F3
  242.     JA    J2DST        ; No, store with current prefix code
  243. J2SRC:    FIXUP    SUBB3,-1,,,J2DST-J2SRC
  244. ; B102
  245.     MOV    CL,2
  246.     FIXUP    XORB3,-2,0B1H
  247. ; D2C8
  248.     ROR    AL,CL
  249.     FIXUP    XORX1,-3,,0D2H,2
  250. ; 92
  251.     XCHG    DX,AX        ; Yes, just save shifted value
  252.     FIXUP    XORW2,-2,0C8H,92H
  253. ; 75EF
  254.     JNZ    J3DST        ; No, contine loop
  255. J3SRC:    FIXUP    SUBB4,-1,,,J3DST-J3SRC
  256. ; 75D7
  257. J0JMP:    JNZ    J0DST        ; (Dummy branch used to clear prefetch queue)
  258. J0SRC:    FIXUP    XORBXX,-1,J0DST-J0SRC
  259.     DB    34H        ; Skip over next byte (34H = XOR AL,nn opcode)
  260.  
  261. DATA:    DB    "$"        ; CRLF data to make sure JL J1DST taken first time
  262.  
  263. GENCOM:    PUSH    CS            ; Allow use without EXE2BIN
  264.     POP    DS
  265.     MOV    DX,Offset LOADER    ; Output LOADER code (!)
  266.     MOV    AH,9
  267.     INT    21H
  268.     CLD
  269.     MOV    SI,Offset CODARE    ; Pointer to real MSBPCT code
  270.     XOR    BP,BP            ; Reset columns left counter
  271.     MOV    BH,17            ; Assure that BH not in range '0'-'3'
  272. BYTLOP:    MOV    AX,0C01H
  273.     SUB    AL,[SI]            ; Convert MSBPCT code to loader format
  274.     INC    SI
  275.     MOV    CL,2
  276.     SHL    AX,CL            ; First byte is top 2 bits of byte+43H
  277.     NOT    AL
  278.     SHR    AL,CL            ; Second byte is low 6 bits of -byte-3
  279.     ADD    AL,35H            ; Based value is '5' for second byte
  280.     CMP    AH,BH            ; Same prefix as previous byte?
  281.     MOV    BH,AH
  282.     XCHG    DX,AX
  283. OUTBYT:    XCHG    DH,DL            ; Swap output order
  284.     JZ    OUTNHI            ; Skip unnecessary prefix byte
  285.     DEC    BP
  286.     JG    OUTNCR            ; Not 72 chars on the line yet
  287.     PUSH    DX
  288.     MOV    DX,Offset CRLF        ; 72 chars on line, add CR LF
  289.     MOV    AH,9
  290.     INT    21H
  291.     MOV    BP,72            ; Restart line pointer
  292.     POP    DX
  293. OUTNCR:    MOV    AH,2            ; Output a byte
  294.     INT    21H
  295. OUTNHI:    XOR    DL,DL            ; Clear out used code byte
  296.     AND    DH,DH            ; Anything more to print?
  297.     JNZ    OUTBYT
  298.     CMP    SI,Offset CODEND    ; End of area?
  299.     JNZ    BYTLOP
  300.     MOV    DX,Offset ENDTXT    ; Yes, add trailer: 34H and CR LF
  301.     MOV    AH,9
  302.     INT    21H
  303.     MOV    AH,4CH            ; End GENCOM program section
  304.     INT    21H
  305.  
  306. ENDTXT    DB    34H            ; End of file marker for loader
  307. CRLF    DB    13,10,"$"
  308.  
  309. CODE ENDS
  310.     END    START
  311.