;; tinyup.asm
;;
	TITLE	Tinyup

Comment	*
	(C) A.I. Architects, 1988
	A.I. Architects CONFIDENTIAL and TRADE SECRET
*

	include	data.inc

; Externals

	EXTRN	OS386_Init_Machine:FAR
	EXTRN	OS386_Create_Task:FAR
	EXTRN	OS386_Task_Control:FAR
	EXTRN	OS386_Get_Exit_Code:FAR
	EXTRN	OS386_Use_Bound_Kernel:FAR
	EXTRN	OS386_Exit_Loader:FAR
	EXTRN	OS386_Declare_RPC:FAR
	EXTRN	OS386_Delete_RPC:FAR

	EXTRN	p_rpc:FAR
	EXTRN	_dump_regs:NEAR


; Macros

fail	MACRO	string
local	string_addr, skip_string
	call	OS386_Exit_Loader
	push	cs
	pop	ds
	jmp	skip_string
string_addr:
	db	string, 13, 10, '$'
skip_string:
	mov	dx, OFFSET string_addr
	jmp	failure
ENDM


dosfail	MACRO string
local	string_addr, skip_string, skip_fail
	jnc	skip_fail
	fail	string
skip_fail:
ENDM


STKSIZE	equ	100h


STACK	SEGMENT PARA STACK 'STACK'
	db	STKSIZE dup ("S")
STACK	ENDS

_TEXT	SEGMENT PARA PUBLIC 'CODE'
_TEXT	ENDS

_DATA	SEGMENT  PARA PUBLIC 'DATA'
	ASSUME cs:_TEXT, ss:STACK, ds:nothing, es:nothing

	PUBLIC	_shared
_shared		real_data	<>	; must be first

taskid	dw	?
comlen	dw	0
comline db	256 dup (?)
rpc_name	db	'PGLUE.EXE',0
copyright	db	'Copyright (c) 1991 StarNet Communications Corp.',13,10,'$'
_DATA	ENDS

c_common	SEGMENT  WORD PUBLIC 'BSS'
c_common	ENDS

_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS

zz	SEGMENT PARA PUBLIC
zz	ENDS

DGROUP	GROUP	_DATA, c_common, _BSS

_TEXT	SEGMENT PARA PUBLIC 'CODE'

	PUBLIC	main
main	PROC NEAR

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

;	mov	sp, STKSIZE			; make a stack

;; shrink memory to a minimum

	mov	bx,zz
	inc	bx				; fencepost guard
	mov	ax,es				; PSP
	sub	bx,ax

	mov	ah, 04Ah			; adjust segment
	int	21h
	  dosfail "UP: Cannot adjust memory"

	mov	ax, 1				; if needed
	push	ax
	call	OS386_Use_Bound_Kernel
	pop	ax

	mov	ax, 1				; M_COLD
	push	ax
	call	OS386_Init_Machine
	add	sp, 2
	cmp	ax, 0
	je	init_ok
	  fail	"UP: Init_Machine failed"
init_ok:

;	mov	dx, offset copyright
;	mov	ah, 9h			; out string
;	int	21h

	push	ds
	mov	ax, OFFSET DGROUP:taskid	; &taskid
	push	ax

	mov	ax, ES:2Ch			; known loc of env. para
	push	ax
	xor	ax, ax
	push	ax

	call	copy_comline
	push	ds
	mov	ax, OFFSET DGROUP:comlen
	push	ax

	xor	ax, ax
	push	ax				; Offset = 0
	push	ax

	call	find_my_name			; char *path
	push	ax
	push	bx

	call	OS386_Create_Task
	add	sp, 20
	cmp	ax, 0
	je	create_ok
	  fail	"UP: error creating task"
create_ok:

	; declare the real procedure
	push	cs
	mov	ax,offset p_rpc
	push	ax

	IFDEF	notdef
	push	cs
	mov	ax,offset init_rpc
	push	ax
	ENDIF
	xor	ax,ax
	push	ax
	push	ax

	push	ds
	mov	ax,offset rpc_name
	push	ax
	call	OS386_Declare_RPC
	add	sp,12
	or	ax,ax
	jz	rpc_ok
	  fail	"UP: error creating RPC"

rpc_ok:
	sub	ax,ax				; T_GO = 0
	push	ax

	mov	ax, taskid
	push	ax				; taskid
	call	OS386_Task_Control
	add	sp, 4
	push	ax				; save return code

	; Zero rps_handle in case there was a crash.  This way, dump()
	; will still work.
	xor	al,al
	mov	_shared.rps_handle,al

	push	ds
	mov	ax,offset rpc_name
	push	ax
	call	OS386_Delete_RPC
	add	sp,4

	pop	ax
	cmp	ax,30				; R_EXIT
	jz	exit_ok

	push	ax
	mov	ax,taskid
	push	ax
	call	_dump_regs
	add	sp,4

exit_ok:
	call	OS386_Get_Exit_Code
        push    ax
	call	OS386_Exit_Loader
        pop     ax
	mov	ah, 4Ch			; AX has exit code returned from 
	int	21h			; Get_Exit_Code
	hlt

failure:
	mov	ah, 9h			; out string
	int	21h
	mov	ah, 4Ch			; exit
	mov	al, 1			; error code
	int	21h
	hlt				; should never get here


main	ENDP




;;		Find my name
;;	args:
;;		es		psp address
;;	res:
;;		ax:bx		pointer to current program name
;;
find_my_name PROC NEAR
	push	es

	mov	ax, es:[02Ch]
	mov	es, ax	
	xor	di, di		; es:di points to env.

	xor	al, al

fmn_again:
	mov	cx, 0FFFFh	; loop for a long time
	repne	scasb		; go get a null
	cmp	BYTE PTR es:[di], 0
	  jne	fmn_again

	add	di, 3		; skip null and 2-byte count
	mov	ax, es
	mov	bx, di

	pop	es
	ret
find_my_name	ENDP



;;
;;
copy_comline PROC NEAR
	
	mov	cx,es				; PSP
	mov	dx,ds				; DGROUP

	; swap PSP and DGROUP
	mov	ds,cx
	ASSUME	ds:nothing
	mov	es,dx
	ASSUME	es:DGROUP

	mov	si, 81h				; location of comline
	xor	cx, cx
	mov	cl, ds:[80h]
	mov	es:[comlen], cx			; store length
	add	cx, 1				; transfer CR too

	mov	di, OFFSET DGROUP:comline

	cld
	rep	movsb

	mov	cx,ds
	mov	ds,dx
	ASSUME	ds:DGROUP
	mov	es,cx
	ASSUME	es:nothing
	ret

copy_comline ENDP	


_TEXT	ENDS

end	main
