*------------------------------------------------------------------------------
*
*  ks.asm - startup code for k.asm
*  
*------------------------------------------------------------------------------

	Section	Startup_Trash,code

******* Included Files *************************************************

	INCLUDE "keys.i"


******* Imported *******************************************************

	xref	IHandler	
	xref	ConIOBlock
	xref	InpIOBlock
	xref	IntRec
	xref	TheTitle
	xref	DefinedKeys
	xref	StringBuf
	xref	AddKey
	xref	FileReadChar
	xref	_bopen
	xref	_bclose
	xref	_main


******* Exported *******************************************************

	xdef	_SysBase
	xdef	_DOSBase
	xdef	_IntuitionBase	
	xdef	_exit

	xdef	KeyFileName		; pointer to keyfilename to load.
	xdef	NWPointer		; pointer to NewWindow structure.
	xdef	FreePort		; a small town in Maine.

*------------------------------------------------------------------------------
startup:
	movem.l	a0/d0,-(sp)

	;------ get Exec's library base pointer:
	move.l	4,a6
	move.l	a6,_SysBase

	;------ Open the needed libraries
	bsr	OpenLibs
	beq	_abort0

	;------ if a key filename was specified, fetch it.
	movem.l	(sp)+,d0/a0
	bsr	LoadKeyFile
	beq	_abort1

	;------ Allocate the NewWindow structure for later use...
	bsr	AllocNewWindow
	beq	_abort2

	;------ Launch the process.
	IFEQ	Debug
	bsr	LaunchProc
	beq	_abort3
	clr.l	d0		; gimme a zero return code
	ENDC

	IFNE	Debug
	jsr	_main
	jmp	_exit
	ENDC
	rts

*------------------------------------------------------------------------------
LoadKeyFile 	

	;------ if the user specified a key filename on the command line,
	;------ read in the file.
	
	;------ skip leading whitespace.
0$	move.b	(a0)+,d1		; Fetch a character
	subq.l	#1,d0			; Subtract Command string length
	ble.s	8$			; if zero, leave
	cmp.b	#' ',d1			; Skip spaces
	ble.s	0$

	;------ At this point, we have something on the command line. 
	;------ Copy it to StringBuf, and null-terminate it.
	lea	-1(a0),a0
	lea	StringBuf,a1

2$	move.b	(a0)+,(a1)+
	cmp.b	#' ',-1(a1)
	bgt.s	2$

	clr.b	-1(a1)

	;------ Attempt to open the file
	move.l	#StringBuf,d1
	move.l	#MODE_OLDFILE,d2
	move.l	#2048,d3
	jsr	_bopen
	move.l	d0,d4
	bne.s	4$

	rts
	
4$	move.b	#' ',d5
	lea	StringBuf,a2
	bsr	FileReadItem
	beq.s	6$

	jsr	AddKey
	cmpa.l	#0,a0
	beq.s	6$

	move.b	#10,d5
	lea	kr_MacStr(a0),a2
	bsr	FileReadItem
	bra.s	4$

6$	move.l	d4,d1
	jsr	_bclose
8$	moveq	#1,d0
	rts

*------------------------------------------------------------------------------
FileReadItem
	;------ This routine will read either the key def or the macro
	;------ def from the file depending on the delimiter.

	clr.l	d6		; Keep a character count.

0$	jsr	FileReadChar
	tst.l	d0
	beq.s	4$

	cmp.b	#76,d6
	bge.s	4$

	cmp.b	(a2),d5
	beq.s	2$

	addq.l	#1,a2
	addq.l	#1,d6
	bra.s	0$
	
2$	clr.b	(a2)
	moveq	#1,d0
4$	rts


*------------------------------------------------------------------------------
OpenLibs	
	;------ Open dos.lib and intuition.lib

	lea	DOSName(pc),A1
	clr.l	d0
	ExecF	OpenLibrary
	move.l	d0,_DOSBase
	beq.s	0$
	
	lea	IntName(pc),A1
	clr.l	d0
	ExecF	OpenLibrary
	move.l	d0,_IntuitionBase
0$	rts


*------------------------------------------------------------------------------
AllocNewWindow
	;------ Allocate a NewWindow structure and set up some of its fields.

	;------ First, get some mem!
	move.l	#nw_SIZE,d0
	move.l	#(MEMF_PUBLIC!MEMF_CLEAR!MEMF_CHIP),d1
	ExecF	AllocMem
	
	;------ Make sure we got the memory
	tst.l	d0
	bne.s	0$
	
	rts			; Return with error

0$	move.l	d0,a0
	
	move.w	#640,nw_Width(a0)
	move.w	#22,nw_Height(a0)
	move.b	#1,nw_BlockPen(a0)
	move.l	#(ACTIVATE!SMART_REFRESH),nw_Flags(a0)
	move.l	#TheTitle,nw_Title(a0)
	move.l	a0,NWPointer
	rts
	

*------------------------------------------------------------------------------
LaunchProc
	;------ Patch the segment list, and create the process. We will leave 
	;------ d3 pointing the segment after this one. While we are at it, 
	;------ fetch a pointer to the command name into d1. This will become
	;------ the name of the process.
	
	move.l	ThisTask(a6),a0		; Fetch a ptr to our Tcb.
	move.l	pr_CLI(a0),a0		; Fetch the bptr to the cli struct
	adda.l	a0,a0
	adda.l	a0,a0
	move.l	cli_CommandName(a0),a1
	add.l	a1,a1			; bcpl pointer conversion
	add.l	a1,a1

	;------ Now copy the command name (which is a bstr) to cmdname,
	;------ and make it a C string in the process.
	lea	cmdname(pc),a2
	move.l	a2,d1			; Save ptr in d1
	clr.l	d0
	move.b	(a1)+,d0		; Get the string length
	bra.s	2$

0$	move.b	(a1)+,(a2)+
2$	dbf	d0,0$
	
	clr.b	(a2)			; Null-terminate the string.

	move.l	cli_Module(a0),a0	; Fetch the bptr to the seg-list.
	adda.l	a0,a0
	adda.l	a0,a0
	move.l	(a0),d3			; Fetch ptr to next segment.
	clr.l	(a0)			; Terminate the list.
	
	;------ Save the new start of the segment list so we can unload
	;------ it later.
	move.l	d3,StartSeg

	;------ Create the process....
	clr.l	d2			; Priority of zero.
	move.l	#2048,d4		; Stack size of 2k bytes.

	DosF	CreateProc
	tst.l	d0
	rts



*------------------------------------------------------------------------------
* _abortx
	;------ This routine is called if we encounter any errors before the
	;------ process is started. It will free all allocated resources and
	;------ return an error code.
	
_abort3
	;------ Cannot create process
	add.l	#1,rc
	jsr	FreeNewWindow

_abort2
	;------ Cannot allocate a NewWindow structure
	add.l	#1,rc
	jsr	KillKeys

_abort1
	;------ Cannot open specified key file.
	add.l	#1,rc

_abort0
	;------ Cannot open librarie(s)
	add.l	#1,rc
	jsr	CloseLibs
	move.l	rc,d0
	rts


cmdname		ds.b	34	
rc		dc.l	100
DOSName		dc.b	'dos.library',0
IntName		dc.b	'intuition.library',0


*------------------------------------------------------------------------------
*
*  This is the first segment of resident code.
*
*------------------------------------------------------------------------------
	Section	KeyCode,code

	;------ Go to the program's main entry point
	bsr	_main
	
_exit:
	bsr	KillKeys

	bsr	RemoveInputHandler
	bsr	CloseInputDevice
	
	move.l	InpIOBlock,a0
	bsr	FreeIOBlock

	move.l	ConIOBlock,a0
	bsr	FreeIOBlock

	bsr	FreeNewWindow
	
	bsr	CloseLibs

	;------ Unload the code.
	move.l	StartSeg(pc),d1
	DosF	UnLoadSeg

	clr.l	d0
	rts

*------------------------------------------------------------------------------
KillKeys
	;------ Delete the macro list.
	lea.l	DefinedKeys(pc),a2
	move.l	kr_Next(a2),a2

0$	cmpa.l	#0,a2
	beq.s	2$

	move.l	kr_Next(a2),a3
	
	move.l	a2,a1
	move.l	#kr_SIZEOF,d0	
	ExecF	FreeMem

	move.l	a3,a2
	bra.s	0$

2$	rts

*------------------------------------------------------------------------------
RemoveInputHandler
	;------ Tell the input.device to stop sending us stuff.
	move.l	InpIOBlock(pc),a1
	move.w	#IND_REMHANDLER,IO_COMMAND(a1)
	move.l	#IntRec,IO_DATA(a1)

	;------ Goodbye handler!
	ExecF	DoIO
	rts
	

*------------------------------------------------------------------------------
CloseInputDevice
	;------ Adios device!
	move.l	InpIOBlock(pc),a1
	ExecF	CloseDevice
	rts

*------------------------------------------------------------------------------
FreePort
	move.l	a0,a2

	move.b	#-1,LN_TYPE(a2)
	move.l	#-1,LH_HEAD(a2)

	clr.l	d0
	move.b	MP_SIGBIT(a2),d0
	LibF	FreeSignal
	
	move.l	a2,a1
	move.l	#MP_SIZE,d0	
	LibF	FreeMem
	rts

*------------------------------------------------------------------------------
FreeIOBlock
	move.l	a0,a3
	move.l	MN_REPLYPORT(a3),a0
	bsr	FreePort

	move.l	a3,a1
	move.l	#IOSTD_SIZE,d0
	ExecF	FreeMem
	rts

*------------------------------------------------------------------------------
FreeNewWindow
	move.l	NWPointer(pc),a1
	move.l	#nw_SIZE,d0
	ExecF	FreeMem
	rts


*------------------------------------------------------------------------------
CloseLibs
	move.l	_DOSBase(pc),d0
	beq.s	0$

	move.l	d0,a1
	ExecF	CloseLibrary
	
0$	move.l	_IntuitionBase(pc),d0
	beq.s	2$

	move.l	d0,a1
	ExecF	CloseLibrary

2$	rts




_SysBase 	dc.l	0
_DOSBase	dc.l	0
_IntuitionBase	ds.l	1	

StartSeg	ds.l	1		; Pointer to procs first segment.
KeyFileName	ds.l	1		; Pointer to keyfilename to load.
NWPointer	ds.l	1		; Pointer to NewWindow structure.
   END



