	title INIT - Initialization routines

	.286p

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

CONST	SEGMENT WORD PUBLIC 'CONST'
CONST	ENDS
_DATA	SEGMENT WORD PUBLIC 'DATA'
_DATA	ENDS
_BSS	SEGMENT WORD PUBLIC 'BSS'
_BSS	ENDS

STACK	SEGMENT WORD STACK 'STACK'
	ALIGN	16
	PUBLIC	mystack, heap, eheap
mystack	db	1000h dup (?)
heap	db	2000h dup (?)
eheap	dw	0
; You're probably wondering why I didn't just say:
; eheap	label	word
; on the line above.  The reason I initialized part of the STACK segment
; is to make the linker create a big file with all of STACK and BSS.
; The reason for this is that OS/396 seems to ignore the MINALLOC value
; in the .EXE header and doesn't allocate the memory needed.
STACK	ENDS

DGROUP	GROUP	CONST,_DATA,_BSS,STACK

_TEXT	SEGMENT WORD PUBLIC 'CODE'
	EXTRN	__cinit:NEAR, __setenvp:NEAR, __setargv:NEAR, _main:NEAR
_TEXT	ENDS

_DATA	SEGMENT
	EXTRN	__asizds:WORD, __atopsp:WORD, __nheap_desc:WORD, __psp:WORD
	EXTRN	_environ:WORD, ___argc:WORD, ___argv:WORD
	EXTRN	_end:WORD, _edata:WORD
	PUBLIC	nums
nums	db	'0123456789abcdef'
_DATA	ENDS

_BSS	SEGMENT
savesp	dw	?
savess	dw	?
pstack	dw	?
	PUBLIC	n_buf
n_buf	db	6 dup (?)
_BSS	ENDS

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

_TEXT	SEGMENT
	EXTRN	_rpc_entry:NEAR

	PUBLIC	my_psp
my_psp	db	0100h dup (?)

init_rpc	PROC	FAR
	; We need some C startup code.  This stuff is stolen from crt0.obj
	; from the C library.
	; Since this routine is called from OS386, we can trash all of the
	; registers.
	; We need to do this stuff in order to use the malloc routines
	; which are needed by the PC/NFS toolkit.

	mov	ax,DGROUP
	mov	es,ax
	ASSUME	es:DGROUP

	; Zero BSS
	cld
	lea	di,_edata
	lea	cx,_end
	sub	cx,di
	xor	ax,ax
	rep	stosb

	; Copy our PSP
	mov	ah,62h
	int	21h
	mov	ds,bx	; PSP segment
	ASSUME	ds:nothing

	mov	dx,_TEXT
	; The first thing in the _TEXT segment always starts at 10h,
	; so incrementing the PSP segment by one will point us to my_psp
	inc	dx

	mov	es,dx
	ASSUME	es:nothing
	xor	si,si	; offset of PSP
	mov	di,si
	mov	cx,80h	; sizeof PSP in words
	rep	movsw

	mov	bx,DGROUP
	mov	ds,bx
	ASSUME	ds:DGROUP

	; setup my stack
	mov	savess,ss
	mov	savesp,sp

	mov	ss,bx
	lea	sp,heap

	; Scribble in our PSP the top of our memory segment.
	lea	ax,eheap
	dec	ax
	mov	__asizds,ax

	inc	ax
	shr	ax,4
	add	ax,bx
	mov	es:[2],ax

	; I have no idea what this does, but I have an idea that it
	; has somthine to do with the near heap.
	; It has been copied from crt0.asm.
	lea	bx,__nheap_desc
	mov	[bx],ss		; now this is DS
	mov	4[bx],sp	; top of all memory
	mov	ax,0fffeh
	push	ax
	mov	10[bx],sp
	not	ax
	push	ax
	mov	word ptr 6[bx],sp
	mov	word ptr 8[bx],sp
	mov	__atopsp,sp
	mov	__psp,es

	call	__setenvp
	call	__setargv
	xor	bp,bp
	call	__cinit
	mov	pstack,sp	; remember stack pointer
	push	_environ
	push	___argv
	push	___argc
	call	_main

	; restore our stack
	mov	ss,savess
	mov	sp,savesp

	; We're done with the clib stuff!
	lea	dx,p_rpc
	mov	ax,cs
	mov	ds,ax
	ASSUME	ds:_TEXT
	ret
init_rpc	ENDP

	; real procedure entry point
	; called by kernel with:
	; CX	= # bytes in transaction buffer
	; AX	= max # of bytes to return
	; DS:DX = transaction buffer
	; return AX = # bytes returned
	;
	; push this stuff on the stack and call the C routine.
	ASSUME	ds:nothing
p_rpc		PROC	FAR
	mov	ax,ds
	mov	es,ax
	ASSUME	es:nothing

	mov	ax,DGROUP
	mov	ds,ax
	ASSUME	ds:DGROUP

	; setup my stack
	mov	savess,ss
	mov	savesp,sp
	mov	ss,ax
	mov	sp,pstack

	push	cx
	push	es
	push	dx
	call	_rpc_entry
	pop	dx
	pop	es
	pop	dx
	mov	cx,ax		; save return value

	; restore our stack
	mov	ss,savess
	mov	sp,savesp

	; set DS:DX to point back to buffer
	mov	ax,es
	mov	ds,ax
	ASSUME	ds:nothing

	mov	ax,cx		; return value

	ret
p_rpc		ENDP

	ASSUME	ds:DGROUP

	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
	xor	bl,bl
	mov	n_buf+4,bl
	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
	lea	bx,n_buf
	jmp	short @dfputs
@printn	ENDP

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

_TEXT	ENDS
	END	init_rpc
