; C0.ASM--
; Copyright (c) 1996-2010 Hjort Nidudsson
;
; Start Up Code for DOS
;
; define:
; 	__WCC__ to include CONST, CONST2 and main_
; 	DEBUG   to include DATASEG@,__MMODEL
;
; Change history:
; 02/28/10 - added Ctrl-C handler (int 23)
; 02/28/10 - added extern System Error handler (int 24)
;
ifndef __c__
 ifndef __l__
	.you must supply a model symbol.
 endif
endif
	.186

FCODE	EQU	8000h
FDATA	EQU	4000h

ifdef __c__
	DIST  	EQU    	<NEAR>
	MMODEL	EQU	FDATA+3
endif

ifdef __l__
	DIST  	EQU    	<FAR>
	LPROG 	EQU	1
	MMODEL	EQU	FCODE+FDATA+4
endif

__BSS__	EQU	1

_TEXT	SEGMENT	WORD public 'CODE'
_TEXT	ENDS
_DATA	SEGMENT	PARA public 'DATA'
_DATA	ENDS
_INIT_	SEGMENT	WORD public 'INITDATA'
_INIT_	ENDS
_IEND_	SEGMENT WORD public 'INITDATA'
_IEND_	ENDS
ifdef __WCC__
CONST	SEGMENT	WORD public 'DATA'
CONST	ENDS
CONST2	SEGMENT	WORD public 'DATA'
CONST2	ENDS
endif
ifdef __BSS__
_BSS	SEGMENT WORD public 'BSS'
_BSS	ENDS
_BSSEND SEGMENT BYTE public 'BSSEND'
_BSSEND ENDS
endif
_STACK	SEGMENT STACK 'STACK'
_STACK	ENDS

ifdef __WCC__
	DGROUP GROUP _DATA,CONST,CONST2,_INIT_,_IEND_,_BSS,_BSSEND,_STACK
else
 ifdef __BSS__
	DGROUP GROUP _DATA,_INIT_,_IEND_,_BSS,_BSSEND,_STACK
 else
	DGROUP GROUP _DATA,_INIT_,_IEND_,_STACK
 endif
endif

	extrn _stklen:	WORD
ifdef __WCC__
	extrn main_:	DIST
else
	extrn main:	DIST
endif

_TEXT	SEGMENT
	ASSUME  cs:_TEXT
START	PROC
	mov	ah,30h
	int	21h
	mov	bp,ds:[0002h]
	mov	bx,ds:[002Ch]
	mov	dx,SEG _DATA
	mov	ds,dx
	ASSUME  ds:DGROUP
	mov	_osversion,ax
	mov	_psp,es
	mov	envseg,bx
	mov	heaptop,bp
	call	SAVE_VECTORS
	mov	ax,envseg
	mov	es,ax
	xor	di,di
	mov	bx,di
	mov	cx,7FFFh
	cld
    get_environ:
	mov	al,0
	repnz	scasb
	or	cx,cx
	jz	bad_environ
	inc	bx
	cmp	es:[di],al
	jnz	get_environ
	or	ch,80h
	neg	cx
	mov	envlen,cx
	shl	bx,2
	add	bx,16
	and	bl,0F0h
	mov	envsize,bx
	mov	dx,ss
	sub	bp,dx
	mov	di,_stklen
	shr	di,4
	inc	di
	cmp	bp,di
	jb	bad_environ
	mov	bx,di
	add	bx,dx
	mov	heapbase,bx
	mov	brklvl,bx
	mov	ax,_psp
	sub	bx,ax
	mov	es,ax
	mov	ax,4A00h
	int	21h
	mov	ax,OFFSET DGROUP:_dsstack
	add	ax,_stklen
	mov	dx,ds
	mov	ss,dx
	mov	sp,ax
	ASSUME  ss:DGROUP
	jmp	init_bss
    bad_environ:
	jmp	_abort
    init_bss:
	xor	ax,ax
	mov	bp,ax
  ifdef __BSS__
	mov	dx,ss
	mov	es,dx
	mov	di,OFFSET DGROUP:bdata@
	mov	cx,OFFSET DGROUP:edata@
	sub	cx,di
	cld
	rep	stosb
  endif
    initialize:
	mov	si,OFFSET DGROUP:InitStart
	mov	di,OFFSET DGROUP:InitEnd
    initialize_00:
	cmp	si,di
	je	call_main
	call	WORD PTR [si]
	add	si,2
	jmp	initialize_00
    call_main:
	mov	ax,C0_argc
	mov	bx,C0_argv
	mov	cx,C0_argv+2
  ifdef __WCC__
	push	cx
	push	bx
	push	ax
	call	main_
  else
	push	ax
	push	cx
	push	bx
	call	main
  endif
	push	ax
	call	exit
START	ENDP

INT24_HANDLER:
	push	ds
	push	ss
	pop	ds
	mov	sys_erflag,ah
	mov	sys_erdrive,al
	mov	ax,di
	mov	ah,0
	mov	sys_ercode,ax
	mov	WORD PTR sys_erdevice,si
	mov	WORD PTR sys_erdevice+2,bp
	mov	al,3
	cmp	WORD PTR sys_erproc,0
	je	INT24_00
	; PUSH ES BX CX DX
	call	sys_erproc
	; POP DX CX BX ES
INT24_00:
	pop	ds

INT23_HANDLER:
	iret

SAVE_VECTORS:
	mov	ax,3523h
	int	21h
	mov	WORD PTR Interrupt_23,bx
	mov	WORD PTR Interrupt_23+2,es
	mov	ax,3524h
	int	21h
	mov	WORD PTR Interrupt_24,bx
	mov	WORD PTR Interrupt_24+2,es
	push	ds
	push	cs
	pop	ds
	mov	ax,2523h
	mov	dx,OFFSET INT23_HANDLER
	int	21h
	mov	ax,2524h
	mov	dx,OFFSET INT24_HANDLER
	int	21h
	pop	ds
	ret

	public  exit
	public  _abort
	public	stderrmsg
	public  _terminate
	public 	_restorezero

stderrmsg PROC
	mov	ah,40h
	mov	bx,2
	int	21h
	ret
stderrmsg ENDP

_abort	PROC	DIST
	mov	cx,sizeabortmsg
	mov	dx,OFFSET DGROUP:abortmsg
	call	stderrmsg
	push	3
	call	exit
_abort	ENDP

exit	PROC DIST
	call	_restorezero
exit	ENDP

_terminate PROC	DIST
	mov	bp,sp
    ifdef LPROG
	mov	al,[bp+4]
    else
	mov	al,[bp+2]
    endif
	mov	ah,4Ch
	int	21h
_terminate ENDP

_restorezero PROC
	push	ds
	lds	dx,Interrupt_23
	mov	ax,2523h
	int	21h
	pop	ds
	push	ds
	lds	dx,Interrupt_24
	mov	ax,2524h
	int	21h
	pop	ds
	ret
_restorezero ENDP

ifdef DEBUG
__MMODEL DW	MMODEL
	public	__MMODEL
endif

_TEXT	ENDS

_DATA	SEGMENT
ifdef DEBUG
DATASEG@ LABEL  BYTE
	public 	DATASEG@
endif
NULL	LABEL	WORD
cp_null	DB	0,0,0,0
abortmsg DB	'Abnormal program termination', 13, 10
sizeabortmsg	= $ - abortmsg
C0_argc		DW	0
C0_argv		DW	0
		DW	0
_psp		DW 	0
envlen	  	DW 	0
envseg		DW 	0
envsize	  	DW 	0
_osversion	LABEL	WORD
_osmajor	DB	0
_osminor	DB	0
errno		DW	0
doserrno	DW	0
ifdef LPROG
 sys_erproc	DD	0
else
 sys_erproc	DW	0
endif
sys_erdevice    DD	0
sys_ercode	DW	0
sys_erflag	DB	0
sys_erdrive	DB	0
Interrupt_24	DD	?
Interrupt_23	DD	?
heaptop		DW	0
heapbase	DW	0
heapfree	DW	0
brklvl		DW	0


	public	C0_argc
	public	C0_argv
	public	_psp
	public	envseg
	public	envlen
	public	envsize
	public	_osversion
	public	_osminor
	public	_osmajor
	public	errno
	public	doserrno
	public  sys_erdevice
	public  sys_ercode
	public  sys_erflag
	public  sys_erdrive
	public  sys_erproc
	public	heaptop
	public	heapbase
	public	heapfree
	public	brklvl

_DATA	ENDS

_INIT_	SEGMENT	WORD public 'INITDATA'
InitStart LABEL BYTE
_INIT_	ENDS
_IEND_	SEGMENT WORD public 'INITDATA'
InitEnd LABEL BYTE
_IEND_	ENDS

ifdef __BSS__
_BSS	SEGMENT WORD public 'BSS'
bdata@	LABEL BYTE
_BSS	ENDS
_BSSEND SEGMENT BYTE public 'BSSEND'
edata@	LABEL BYTE
_BSSEND	ENDS
endif

_STACK	SEGMENT
_dsstack LABEL WORD
	public	_dsstack
	DB	124 dup(?)
	DD	564A4A0Ah
_STACK	ENDS

	END	START
