; Date: 27 Aug 86 14:14 EDT ; From: junod@dtrc.ARPA (John Junod) ; Subject: MSBPCT.ASM ; To: info-kermit@cu20b ; ; I have just completed a reconstruction of Kermit on a DEC Rainbow ; using the MSVRB1.BOO file. The target machine had a Vanilla ; MS-DOS disk w/o BASIC or a Terminal Emulator w/file transfer. ; It did have MASM and LINK. I was able to capture the BOO file ; by using "copy aux mskermit.boo" (and you could capture the ; msbpct.asm file by using "copy aux msbpct.asm") and sending ; a control-z at the end from another MS-DOS machine connected ; to the Rainbow's communication port. Since I was unable to ; find an assembly version of MSBPCT I wrote the following ; to reconstruct MSKERMIT.EXE. (Note: you must have the source ; BOO file on the default drive as MSKERMIT.BOO and the ; output will always be MSKERMIT.EXE on the default drive. ; ; If necessary do a "copy" or "rename" of your capture file ; before running the assembled MSBPCT.ASM) ; ; Regards, ; ; John Junod ; Code 1821 ; David Taylor Naval Ship R and D Center (DTNSRDC) ; Bethesda, Md 20084-5000 ; ; DDN: junod@dtrc ; Edit history: ; [v1.0] ; MSBPCT.ASM ; August 27,1986 ; L. John Junod DDN:junod@dtrc ; Code 1821 ; David Taylor Naval Ship R & D Center ; Bethesda, MD 20084-5000 ; ; Note Source BOO file must be on default drive as MSKERMIT.BOO ; Result will be MSKERMIT.EXE on the default drive ; ; Macro Definitions set_dta macro buffer ;set the data transfer mov dx,offset buffer ;address to the proper mov ah,1AH ;buffer int 21H endm read_seq macro FCB ; read buffer full of data mov dx,offset FCB ; from via FCB mov ah,14H int 21H endm display_char macro character ;display character on console mov dl,character mov ah,02H int 21H endm put_char macro character ;write a character to output ; file mov FCB2[14],1 ; one char mov buffer2[0],character set_dta buffer2 ;change to output buffer mov dx,offset FCB2 mov ah,15H int 21H set_dta buffer1 ;change back to input buffer endm open macro FCB ;open a file via the FCB mov dx,offset FCB mov ah,0FH int 21H endm create macro FCB ;overwrite or create a file mov dx,offset FCB ;via the FCB mov ah,16H int 21H endm close macro FCB ;close a file via the FCB mov dx,offset FCB mov ah,10H int 21H endm STKSEG SEGMENT STACK ;setup our stack db 100H dup (?) STKSEG ENDS public unpack,read_char code segment assume cs:code,ss:stkseg,ds:datas,es:nothing ; Main routine to process MSKERMIT.BOO and produce MSKERMIT.EXE ; on the default drive START: mov ax,datas ; save the data segment mov ds,ax set_dta buffer1 ; set dta to input buffer open FCB1 ; file to read set_dta buffer2 ; set the dta to the output buffer create FCB2 ; file to write/overwrite mov cx,1 ; fake out the dec cx in read_char xor si,si ; clear the current input index skipname: call read_char ; skip default BOO output name cmp al,10 ; Linefeed? jne skipname ; No: read until we have it process_char: call read_char ; get an input character if avail cmp al,10 ; skip newlines je process_char cmp al,13 ; skip carriage returns je process_char call unpack ; go unpack a quad or null rep jmp process_char ; read_char ; this routine returns a character in al if available ; if the end-of-file is encountered, the input file ; is closed and the output file is closed after ; appending a final control-Z (26 decimal) read_char proc near dec cx ; read another buffer full? cmp cx,00H je read_line ; yes mov al,buffer1[si] ; no: put char in al cmp al,26 ; end of file? je all_done ; yes: do wrap up inc si ; bump input index ret read_line: set_dta buffer1 ; make sure we are using input buffer read_seq FCB1 ; read buffer full from input file cmp al,01H ; end of file? no data? je all_done ; yes: wrap up cmp al,01H ; end-of-file w/partial record? jg check_more ; yes: go process partial record mov cx,128 ; no: normal read xor si,si ; zero the input buffer index mov al,buffer1[si] ; get 1st char in input buffer inc si ; bump input buffer index cmp al,26 ; end-of-file? je all_done ; yes: wrap up ret check_more: cmp al,03H ; input buffer full? read cancelled? jne all_done ; yes:exit mov cx,128 ; no: process parital record xor si,si ; zero the input buffer index mov al,buffer1[si] ; get 1st char in input buffer inc si ; bump input buffer index cmp al,26 ; end-of-file? je all_done ; yes: wrap up ret all_done: close FCB1 ; close input file put_char 26 ; append eof (control-z) to output file close FCB2 ; close output file mov ah,4CH ; exit back to dos xor al,al ; return a zero int 21H read_char endp ; unpack ; Process a repeat count or quad and return to caller ; if char is ~ (7EH) then read next char as repeat count ; and subtract '0' (30H) to get actual repeat count ; and generate nulls ; else process a quad (ie 4 characters reduced to 3) ; ; AL is assumed to contain a valid character on entry ; unpack proc near cmp al,7EH ; null compress char? jne quad ; no: do a quad P1: call read_char ; yes: get repeat count cmp al,10 ; skip new lines je p1 cmp al,13 ; skip carriage returns je p1 sub al,30H ; get actual repeat count push cx ; save cx for read_char use xor cx,cx ; put count in cx for rep_count loop mov cl,al rep_count: put_char 00H ;output nulls loop rep_count pop cx ; restore cx for read-char use ret ; done with null repeat quad: xor bx,bx ; clear inbyte buffer index sub al,30H ; correct character mov inbyte[bx],al ; save 1st byte inc bx ; bump inbyte buffer index p2: call read_char ; get a character cmp al,10 ; skip newlines je p2 cmp al,13 ; skip carriage returns je p2 sub al,30H ; correct character mov inbyte[bx],al ; save 2nd byte inc bx ; bump inbyte buffer index p3: call read_char ; get a character cmp al,10 ; skip newlines je p3 cmp al,13 ; skip carriage returns je p3 sub al,30H ; correct char mov inbyte[bx],al ; save 3rd byte inc bx ; bump inbyte buffer index p4: call read_char ; get a character cmp al,10 ; skip newlines je p4 cmp al,13 ; skip carriage returns je p4 sub al,30H ; correct char mov inbyte[bx],al ; save 4th byte - all 4 bytes loaded xor ax,ax ; clear ax mov al,inbyte[1] ; inbyte[0] * 4 + inbyte[1] / 16 shr ax,1 shr ax,1 shr ax,1 shr ax,1 xor bx,bx mov bl,inbyte[0] shl bx,1 shl bx,1 add al,bl put_char al ; output 1st decoded byte xor ax,ax ; inbyte[1] * 16 + inbyte[2]/4 mov al,inbyte[2] shr ax,1 shr ax,1 xor bx,bx mov bl,inbyte[1] shl bx,1 shl bx,1 shl bx,1 shl bx,1 add al,bl put_char al ; output 2nd decoded byte xor ax,ax ; inbyte[2] * 64 + inbyte[3] mov al,inbyte[2] shl ax,1 shl ax,1 shl ax,1 shl ax,1 shl ax,1 shl ax,1 add al,inbyte[3] put_char al ; output 3rd decoded byte ret unpack endp code ends ; Data Declarations datas segment FCB1 db 0,"MSKERMITBOO" ; Input file is MSKERMIT.BOO db 25 dup (?) ; on default drive FCB2 db 0,"MSKERMITEXE" ; Output file is MSKERMIT.EXE db 25 dup (?) ; on default drive buffer1 db 128 dup (?) ; Input buffer buffer2 db 128 dup (?) ; Output buffer inbyte db 4 dup (?) ; Unpack temporary buffer datas ends end start