þ a‹R þ w 
&þ m^9     þ hý	 oP    þ nSystem-wide$symbols
$xref

NAME MCSFEC

   data	struc
	oldBP	DW ?	; space for BP
	retAdd	DW ?	; caller's return address
	pEDCBlock	DD ?	; parameters passed to us
	pReturnData DD ?
	pTDCData	DD ?
   data	ends

   dsa	struc
	old_BP	DW ?	; and the base pointer
	return	DW ?	; the return address
	pOutData	DD ?
	pInData	DD ?
   dsa	ends

   extrn edc:byte

CGroup GROUP Code
ASSUME cs:cGroup
CODE segment public 'CODE'


	public	UNTDC
;
; calling sequence for UNTDC:
;	CALL UNTDC (pTDCData, pReturnData, pEDCBlock);
;	DECLARE (pTDCData, pReturnData, pEDCBlock) POINTER;
;
;	TDCData is 24 bytes of 8 bit TDCed (data plus EDC)
;	ReturnData is 16 bytes of 7 bit characters (high order bit zero)
;	EDCBlock is 16 bytes of 5 bit EDC values (high order bits zero)
;
UNTDC	PROC	near
	push	bp
	mov	bp,sp
	push	ds

	les	si,[bp].pTDCData	; ES:SI = pTDCData
	lds	di,[bp].pReturnData	; DS:DI = pReturnData

	mov	cx,1	; for edc loop
	push	cx

	xor	ax,ax
	mov	cx,8
	push	cx
zeroArray:
	mov	ds:[di],ax	; zero out ActualData area
	inc	di	; di points @ end of table
	inc	di
	loop	zeroArray

	pop	cx
	push	di	; save di for Ascii data

	lds	di,[bp].pEDCBlock	; get address for UNedc area
zeroEDC:
	mov	ds:[di],ax	; zero the edc area 
	inc	di
	inc	di
	loop	zeroEDC

	dec	di	; adjust di for end of block
	xchg	di,bx

	pop	di
	push	bx	; save edc ptr for below

; begin unTDCing the ascii data

	dec	di	; adjust di for end of Ascii
nextColumn:
	mov	bx,7	; bit count
nextByte:
	add	si,13	; si points to end of tdc area
	mov	cx,7
nextBit:
	mov	al,es:[si]	; get byte j of tdc'd data
	xchg	cx,bx
	shr	al,cl	;get bit i of byte j to undo
	xchg	cx,bx
	and	al,1
	jz	 zero

	dec	cx
	shl	al,cl	; move bit to correct weight
	inc	cx
	or	 ds:[di],al	;store bit in output array
zero:
	sub	si,2
	loop	nextBit

	inc	si
	dec	di	; point to next byte
	sub	bx,1
	jnc	nextbyte

; now unTDC the EDC data

	mov	dx,7
	pop	bx	; bx contains di from above
	push	di	; save Ascii pointers
	push	si
	xchg	di,bx
	add	si,13	; set indexes for EDC data
UNedc:
	add	si,10	; adjust si to end of tdc'd edc
	mov	cx,4	; only 5 edc bits per byte
UNedc1:
	mov	al,es:[si]	; byte j of edc code
	xchg	dx,cx
	shr	al,cl
	xchg	dx,cx
	and	al,1
	jz	 around

	shl	al,cl
	or	 ds:[di],al	; store bit in edc array
around:
	sub	si,2
	sub	cx,1	; move to next bit weight
	jnc	UNedc1

	dec	di
	sub	dx,1	; DX keeps track of whether 
	jnc	UNedc	; we are doing the even or odd bytes
	xchg	di,bx
	pop	si	; get indexes for Ascii data
	dec	si
	pop	di
	pop	dx
	sub	dx,1
	push	dx
	push	bx
	jnc	nextColumn

	pop	bx
	pop	dx

	pop	ds
	pop	bp
	ret	12	; remove ptrs passed in

UNTDC	endp


	public	TDC
;
; calling sequence
;	CALL TDC (pInData, pOutData);
;	DECLARE (pInData, pOutData) POINTER;
;
;	InData is 16 bytes of 7 bit characters (high order bit ignored)
;	OutData is 24 bytes of 8 bit TDCed (data plus EDC)
;
;	requires the external data block "edc",
;	which contains edc values for bytes.
;	(kept in BitRoutines.plm)
;
TDC	proc	near
	push	bp
	mov	bp,sp

	push	ds

	les	si,[bp].pOutData	; initialize output data to zero
	xor	ax,ax	; zero ax
	mov	cx,12	; zero out 12 words
zloop:
	mov	es:[si],ax
	inc	si	; point to the next word
	inc	si
	loop	zloop

	les	si,[bp].pInData	; get pInData
	add	si,15	; start at end of table

	mov	cx,16	; for i:=16 downto 0
			; 16 to 1 for LOOP instruction
iloop1:
	dec	cx	; make (16 to 1) into (15 to 0)
	mov	bx,cx	; save I for bottom of loop
	push	bx
	lds	di,[bp].pOutData	; get pOutData

;	shr	cx,3	; I div 8
	shr	cx,1
	shr	cx,1
	shr	cx,1

	add	di,cx
	push	di	; save base + I div 8
	add	di,12
	mov	cx,7	; for j:=0 to 6
jloop1:
	dec	cx	; as for I loop
	mov	al,es:[si]	; get Ith byte of ActualData
	shr	al,cl	; get the Jth bit
	and	al,1
	jz	jloop11	; we save time if there isn't a bit to 
			; shift

	xchg	bx,cx
	push	cx
	and	cx,7	; I mod 8
	shl	al,cl	; shift by I mod 8
	pop	cx
	xchg	bx,cx

	or	ds:[di],al	; store the bit
jloop11:
	sub	di,2	; move down in the table (this is
			; faster than DEC, DEC)
	inc	cx	; (6 to 0) to (7 to 1)
	loop	jloop1

	pop	di	; get base + I div 8
	add	di,22	; + 2*J

	mov	al,es:[si]	; ActualData[I]
	and	ax,07fh
	push	bx
	push	es
	mov	bx,ax
	mov	ax,seg edc
	mov	es,ax
	mov	dh,es:edc[bx]
	pop	es
	pop	bx
	mov	cx,5	; for j:=11 downto 7
jloop2:
	dec	cx
	mov	dl,dh	; get edc byte
	shr	dl,cl	; get the Jth bit
	and	dl,1
	jz	jloop21	; don't shift if no bit

	xchg	bx,cx	; (bit j) at (bit I mod 8)
	push	cx
	and	cx,7	; I mod 8
	shl	dl,cl	; put (bit J) at (I mod 8)
	pop	cx
	xchg	bx,cx

	or	ds:[di],dl	; store the bit
jloop21:
	sub	di,2	; move down table
	inc	cx
	loop	jloop2

	dec	si	; move down in ActualData

	pop	cx
	inc	cx
	loop	iloop1

	pop	ds
	pop	bp
	ret	8	; remove parameters

TDC	endp


	public	C8TO7
;
; calling sequence
;	CALL C8TO7 (pInData, pOutData);
;	DECLARE (pInData, pOutData) POINTER;
;
;	InData is 14 bytes of 8 bit characters
;	OutData is 16 bytes of 7 bit characters (high order bit zero)
;
C8TO7	proc	near
	push	bp
	mov	bp,sp
	push	ds

	lds	si,[bp].pInData	; get pInData
	les	di,[bp].pOutData	; get pOutData
	xor	bx,bx	; zero bx to accumulate high order bits in
	
	mov	cx,7	; do c8to7loop1 for first 7 input bytes
c8to7loop1:
	mov	al,ds:[si]	; get 8 bit InData[i], for i := 1 to 7
	inc	si	; next input byte

	mov	ah,al	; copy byte to work space
	and	ah,80h	; isolate high order bit
	or	bl,ah	; copy bit into first accumulate byte
	shr	bl,1	; order accumulated bits low to high order

	and	al,7Fh	; zero out high order bit
	mov	es:[di],al	; put 7 bit byte into output
	inc	di	; next output byte
	loop	c8to7loop1

	mov	cx,7	; do c8to7loop2 for second 7 input bytes
c8to7loop2:
	mov	al,ds:[si]	; get 8 bit InData[i], for i := 8 to 14
	inc	si	; next input byte

	mov	ah,al	; copy byte to work space
	and	ah,80h	; isolate high order bit
	or	bh,ah	; copy bit into second accumulate byte
	shr	bh,1	; order accumulated bits low to high order

	and	al,7Fh	; zero out high order bit
	mov	es:[di],al	; put 7 bit byte into output
	inc	di	; next output byte
	loop	c8to7loop2

	mov	es:[di],bx	; put 2 accumulate bytes on end of output

	pop	ds
	pop	bp
	ret	8	; remove parameters

c8to7	endp


	public	C7TO8
;
; calling sequence
;	CALL C7TO8 (pInData, pOutData);
;	DECLARE (pInData, pOutData) POINTER;
;
;	InData is 16 bytes of 7 bit characters (high order bit ignored)
;	OutData is 14 bytes of 8 bit characters
;
C7TO8	proc	near
	push	bp
	mov	bp,sp
	push	ds

	lds	si,[bp].pInData	; get pInData
	les	di,[bp].pOutData	; get pOutData
	mov	bx,ds:[si+14]	; load 2 bytes holding the high order bits
	
	mov	cx,7	; do C7TO8loop1 for first 7 input bytes
C7TO8loop1:
	mov	al,ds:[si]	; get 7 bit InData[i], for i := 1 to 7
	inc	si	; next input byte

	ror	bl,1	; put next high bit into correct position
	mov	ah,bl	; copy byte to work space
	and	ah,80h	; isolate the desired bit
	or	al,ah	; put the high bit back on the byte

	mov	es:[di],al	; put 8 bit byte into output
	inc	di	; next output byte
	loop	C7TO8loop1

	mov	cx,7	; do C7TO8loop2 for second 7 input bytes
C7TO8loop2:
	mov	al,ds:[si]	; get 7 bit InData[i], for i := 8 to 14
	inc	si	; next input byte

	ror	bh,1	; put next high bit into correct position
	mov	ah,bh	; copy byte to work space
	and	ah,80h	; isolate the desired bit
	or	al,ah	; put the high bit back on the byte

	mov	es:[di],al	; put 8 bit byte into output
	inc	di	; next output byte
	loop	C7TO8loop2

	pop	ds
	pop	bp
	ret	8	; remove parameters

c7to8	endp


   code   ends
   end
