; Micro-X -- an X server for DOS
; Copyright (C) 1992 StarNet Communications Corp.

; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.

; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.

; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

; StarNet Communications Corp.
; 550 Lakeside Dr. #3
; Sunnyvale CA 94086 US
; http://www.starnet.com
; x-dos@starnet.com

	TITLE   support

	.286p

X	equ	4		; for near calls
;X	equ	6		; for far calls

_TEXT	SEGMENT  para PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT PARA PUBLIC 'DATA'
_DATA	ENDS
_BSS	SEGMENT PARA PUBLIC 'BSS'
_BSS	ends
STACK	SEGMENT WORD STACK 'STACK'
STACK	ENDS

DGROUP	GROUP	_DATA,_BSS,STACK

	ASSUME	cs:_TEXT, ds:DGROUP, es:nothing, ss:nothing

_DATA	SEGMENT
nums	db	'0123456789abcdef'
_DATA	ENDS
_BSS	SEGMENT
n_buf	db	6 dup (?)
_BSS	ENDS

EXTRN	_errno:WORD

_TEXT	SEGMENT
		align	2
	PUBLIC  @n_clicks
; u_long _near _fastcall n_clicks(void)
;
;	get the number of timer clicks from BIOS
;
@n_clicks  proc	near
	mov	ah,0
	int	1ah
	mov	ax,dx		; low word
	mov	dx,cx		; high word
	ret
@n_clicks endp

	PUBLIC	@iphcheck, @ipcheck
; u_int near iphcheck(ptr)
; struct iph far *ptr;		; passed as a u_long because of MSC crock
;
; u_int near ipcheck(ptr, len)
; struct iph near *ptr;
; u_int len;
;
;	Internet header checksum
;	header checksum is calculated for a higher level program to verify
;

ipcheck	proc	near
@ipcheck:
	push	ds
	push	si
	mov	si,bx
	mov	cx,ax
	jmp short ipentry

@iphcheck:
	push	ds
        push	si
	mov	ds,dx
	ASSUME	ds:nothing
	mov	si,ax
	mov	cx,20		; 20 bytes in ipheader
ipentry:
	mov	dl,cl		; save low bit
	and	dl,1
	shr	cx,1		; len = len / 2
	sub	bx,bx		; also clears carry
chksum:
	lodsw			; get next word
	adc	bx,ax		; keep adding
	loop	chksum		; til' done

	mov	cl,dl
	jcxz	ipnotodd
	lodsb			; get that last byte
	mov	ah,ch		; clear the high portion
	adc	bx,ax		; add the last one in
				; don't modify CF until the adc instruction
ipnotodd:

	adc	bx,0		; adds the carry bit in
	cmp	bx,-1
	jz	L1
	not	bx		; take one more 1-complement
L1:
	mov	ax,bx
        pop	si
	pop	ds
	ASSUME	ds:DGROUP
	ret
ipcheck	endp

	PUBLIC	_tcpcheck
; u_int near tcpcheck(psptr, tcpptr, tcplen)
; struct pseudotcp near *psptr;
; struct tcph far *tcpptr;
; u_int tcplen;
;
;  TCP checksum
;
_tcpcheck	proc	near
	push	bp
	mov	bp,sp
        push	si
	push	ds

	lds	si,[bp+X+2]	; tcpptr
	ASSUME	ds:nothing
	mov	cx,[bp+X+6]	; count of bytes to test
	mov	dl,cl		; keep a copy of LSB
	and	dl,1		; keep LSB only
	shr	cx,1		; divide by two, round down
	sub	bx,bx           ; clear to begin
rchksum:
	lodsw
	adc	bx,ax		; add to running sum
	loop	rchksum
				; don't modify CF until the adc instruction
	mov	cl,dl
	jcxz	notodd
	lodsb			; get that last byte
	mov	ah,ch		; clear the high portion
	adc	bx,ax		; add the last one in
				; don't modify CF until the adc instruction
notodd:
	pop	ds
	ASSUME	ds:DGROUP
	mov	si,[bp+X]	; psptr
	mov	cx,6		; length of p-hdr in words
pchksum:
	lodsw			; get next word
	adc	bx,ax		; keep adding
	loop	pchksum		; til' done
	adc	bx,0		; adds the carry bit in

	cmp	bx,-1
	jz	L2
	not	bx		; take one more 1-complement
L2:
	mov	ax,bx
        pop	si
	ASSUME	ds:DGROUP
	pop	bp
	ret
_tcpcheck	endp

	PUBLIC	@htonl, @ntohl
; u_long near ntohl(x)
; u_long x;
;
; u_long near htonl(x)
; u_long x;
;
;	swap the bytes of a long integer from PC
;	order (reverse) to in-order.  This will work both ways.
;	returns the new long value
;
longswap	proc	near
@ntohl:
@htonl:
	xchg	ax,dx		; swap high and low ints
	xchg	dh,dl		; swap the bytes also
	xchg	ah,al		; swap the others
	ret
longswap	endp

	PUBLIC	@dfputs
; void _fastcall dfputs(cp)
; char near *cp;
@dfputs	PROC NEAR
	push	si
	mov	si,bx
	mov	ah,2
put_loop:
	lodsb
	or	al,al
	jz	put_exit
	mov	dl,al
	int	21h
	jmp	short put_loop
put_exit:
	pop	si
	ret
@dfputs	ENDP

	PUBLIC	@printn
@printn PROC NEAR
	mov	n_buf+4,0
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf+3,bl
	shr	ax,4
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf+2,bl
	shr	ax,4
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf+1,bl
	shr	ax,4
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf,bl
	mov	bx,offset DGROUP:n_buf
	jmp	short @dfputs
@printn	ENDP

	PUBLIC	@printd
@printd PROC NEAR
	mov	bx,offset DGROUP:n_buf+5
	mov	byte ptr [bx],0
	mov	cx,10		; divide by 10
pd_1:
	xor	dx,dx		; divide number by 10
	div	cx
	add	dl,'0'		; remainder is in dx
	dec	bx
	mov	[bx],dl
	or	ax,ax
	jnz	pd_1		; more to divide
	jmp	short @dfputs
@printd	ENDP

;
;	int open(name, mode)
;	char _far *name;
;	int mode;

	PUBLIC	_open
_open	PROC	NEAR
	ASSUME	ds:DGROUP
	push	bp
	mov	bp,sp
	push	ds
	lds	dx,[bp+X]
	ASSUME	ds:nothing
	mov	al,[bp+X+4]
	mov	ah,3dh
	int	21h
	pop	ds
	ASSUME	ds:DGROUP
	jc	error
	pop	bp
	ret
_open	ENDP

;	int read(fd, buf, size)
;	int fd, size;
;	char *buf;
	PUBLIC	_read
_read	PROC	NEAR
	push	bp
	mov	bp,sp
	mov	bx,[bp+X]
	mov	dx,[bp+X+2]
	mov	cx,[bp+X+4]
	mov	ah,3fh
	int	21h
	jc	error
	pop	bp
	ret
error:
	ASSUME	ds:DGROUP
	mov	_errno,ax
	mov	ax,-1
	pop	bp
	ret
_read	ENDP

;	int close(fd)
;	int fd;
	PUBLIC	_close
_close	PROC	NEAR
	push	bp
	mov	bp,sp
	mov	bx,[bp+X]
	mov	ah,3eh
	int	21h
	jc	error
	pop	bp
	ret
_close	ENDP

; void _far * _fastcall alloc_seg(unsigned short);
	PUBLIC	@alloc_seg
@alloc_seg	PROC	NEAR
	; convert to paragraphs
	add	ax,0fh
	shr	ax,4
	mov	bx,ax
	mov	ah,48h
	int	21h
	jc	alloc_error
	mov	dx,ax		; segment
	xor	ax,ax		; offset will be zero
	ret
alloc_error:
	mov	_errno,ax
	xor	ax,ax
	xor	dx,dx
	ret
@alloc_seg	ENDP

; void _fastcall dealloc_seg(unsigned short);
	PUBLIC	@dealloc_seg
@dealloc_seg	PROC	NEAR
	mov	es,ax
	mov	ah,49h
	int	21h
	ret
@dealloc_seg	ENDP

_TEXT	ends
	end
