Date:    Fri, 19 Feb 88 01:13:04 GMT
From:    granroth%iowasp.span@Sds.Sdsc.Edu (Larry Granroth 319/335-1960)
Subject: tenex conversion for the pc
To:      info-ibmpc@walker-emh.arpa

The following code may come in handy for people who are having difficulty
FTPing binary files from SIMTEL20 or other TOPS-20 systems to MS-DOS PC's.
The program FIX36 was developed on an XT clone with MASM 4.0.  It reads
36-bit groups from standard input and re-packs the data into 32-bit
groups to standard output, removing the 4 extraneous zero bits from each
group.

Larry Granroth
GRANROTH%IOWASP.SPAN@SDS  (soon to be GRANROTH@IOWASP.PHYSICS.UIOWA.EDU)

	page	54,132
	title	FIX36:  fix image ftp's from tops20 systems
;----------------------------------------------------------------------
;
;	FIX36 version 02-18-88  MASM 4.0
;	Copyright (c) 1988 by Larry Granroth
;	This code may be freely distributed for non-commercial purposes
;	only.  Modifications to the code may be made as long as they
;	are clearly documented.
;	
;	When doing an image (or binary) type FTP transfer from a TOPS-20
;	system, the resulting file contains 32-bit data packed in 36-bit
;	groups (each with 4 trailing zero bits).
;	This program reads such a file from standard input and
;	repacks the data, removing the extraneous bits, to standard
;	output.  In certain cases, for example VAX/VMS systems running
;	CMU TCP/IP software, the creation of an image file will result
;	in the file being padded out to an integral number of 512-byte
;	blocks.  If this file is moved to a PC and processed with FIX36,
;	it will still have the extra trailing zeros.
;	Note that, if your FTP implementation supports the feature,
;	the correct transfer type is "TYPE L 8", in which case this
;	program would not be needed.
;
;	usage:
;	C> fix36 <infile.bin >outfile.bin
;
;----------------------------------------------------------------------

cseg	segment	para public 'CODE'
	assume cs:cseg,ds:cseg,es:cseg,ss:cseg

	org	100h

fix36	proc	near

read:	mov	dx, offset buffer	; ds:dx points to buffer
	xor	bx,bx			; stdin file handle 0
	mov	cx,4608			; number of bytes to read (512*9)
	mov	ah,3fh			; read function
	int	21h			; dos call
	jc	abort
	or	ax,ax			; test for zero
	jz	eof
	mov	cx,ax			; save number of bytes read

	mov	si,dx			; ds:si points to first input byte
	mov	di,dx			; ds:di points to first output byte
	cld

first:	movs	word ptr [di],word ptr [si] ; just move 4 bytes
	movs	word ptr [di],word ptr [si]

second:	lods	word ptr [si]		; load next 2 bytes
	rol	ax,1
	rol	ax,1
	rol	ax,1
	rol	ax,1			; rotate 4 bits left
	mov	dx,ax			; save in dx

third:	lods	word ptr [si]		; load next 2 bytes
	mov	bx,ax			; save in bx
	mov	ax,dx			; work on previous 2 bytes
	mov	dx,bx			; save another copy
	shr	bl,1
	shr	bl,1
	shr	bl,1			; shift out lower nibble
	shr	bl,1			;  and position higher nibble
	or	ah,bl			; put higher nibble where it belongs
	stos	word ptr [di]		; restore first corrected word

fourth:	lods	byte ptr [si]		; get 9th byte in cycle
	and	dl,0fh			; mask out higher nibble
	or	dl,al			; put in remaining nibble
	mov	ax,dx			; move back to accumulator
	rol	ax,1
	rol	ax,1
	rol	ax,1
	rol	ax,1			; rotate left one nibble
	stos	word ptr [di]		; restore second corrected word

	sub	cx,9			; work with groups of 9 bytes
	jg	first			; loop if more

	jz	write

	cmp	cx,-4			; this adjusts for a total
	jl	adjust			;  byte count which is not
	sub	cx,1			;  a multiple of 9
adjust: add	di,cx

write:	mov	dx,offset buffer	; get buffer address
	mov	cx,di			; output index
	sub	cx,dx			; number of re-formatted bytes
	mov	bx,1			; stdout file handle 1
	mov	ah,40h			; write function
	int	21h			; dos call
	jc	abort			; abort on error
	jmp	read			; read another buffer

eof:	mov	bx,1			; stdout file handle 1
	mov	ah,3eh			; close function
	int	21h
	jc	abort
	xor	al,al			; successful exit code 0
	jmp	exit

abort:	mov	si,ax			; save the error code
	mov	bx,2			; stderr file handle 2
	mov	cx,16			; 16 characters in error message
	mov	dx,offset errmsg	; ds:dx points to errmsg
	mov	ah,40h			; write function
	int	21h			; dos call
	mov	ax,si			; original error code in al

exit:	mov	ah,4ch			; return to dos
	int	21h

fix36	endp

errmsg	db	13,10,'Fix36 Error',7,13,10
buffer	db	4608 dup (?)

cseg	ends
	end	fix36
