*****************************************************************
*								*
*		COMMAND FILE LOADER FOR CPM68K			*
*		==============================			*
*								*
*	(c)     COPYRIGHT Digital Research 1983			*
*		all rights reserved				*
*								*
*	THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM	*
*	==================================================	*
*								*
*	Description:						*
*	-----------	The command file loader is envoked by   *
*			the CCP after the CCP has successfully  *
*			opened that file.  The loader must	*
*			call the BDOS to obtain the boundries   *
*			of the TPA.  The load parameter block   *
*			defined in this loader holds all the    *
*			memory size and location details.	*
*			Next the loader returns the system to   *
*			its original user #.  The CCP might     *
*			have switched to user zero during its   *
*			search for the file.  Next the default  *
*			dma address is set for the loaded       *
*			program.  Next the command tail is      *
*			placed,along with the first two parsed  *
*			fcb's,into the user basepage.		*
*			Lastly the user stack pointer is set up *
*			and the return address is put on the    *
*			user stack.  An RTE transferes control. *
*			If a load was not successfull, the      *
*			appropriate error message is printed.   *
*								*
*	Created by:	Tom Saulpaugh				*
*								*
*	Last Modified:  3/02/83					*
*								*
*****************************************************************



	.globl _load68k		* make this procedure public
	.globl _user		* global user # before load occured
	.globl _cmdfcb		* parsed fcb
	.globl _tail		* global pointer to command tail
	.globl _fill_fcb	* procedure to fill fcb's
	.globl flags		* ROM SYSTEM INITIALIZATION
	.globl TPAB		* ROM SYSTEM INITIALIZATION


reboot   =  0
printstr =  9
setdma   = 26
chuser   = 32
pgmldf   = 59
gettpa   = 63

_load68k:
*
*	Load the 68k file into the TPA
*	------------------------------
* 
	.text

	move.l	#TPAB,d1	* move in address of tpa parameter block
	move.w  #gettpa,d0	* get function number
	trap	#2		* get the tpa limits 
	move.l  low,lowadr	* put it in the lpb
	move.l  high,hiadr	* put high tpa addr in lpb
	move.l	#_cmdfcb,LPB	* get address of opened fcb
	move.l  #pgmldf,d0	* move in bdos function no
	move.l  #LPB,d1		* d1 points to load block
	trap    #2		* do the program load
	tst	d0		* was the load successful?
	bne     lderr		* if not print error message and return
*
*	return to original user #
*	-------------------------
	move.w	_user,d1	* put user # to switch to in d1
	move.l	#chuser,d0	* put bdos func # in d0
	trap	#2		* do the user # change
*
*	set the default dma address
*	---------------------------
	clr.l	d1		* clear d1 register
	move.l  baspag,d1	* d1 points to user base page
	add	#$80,d1		* d1 points to default dma in base page
	movea.l d1,a1		* save it for later use
	move    #setdma,d0      * move in bdos function no
	trap    #2		* set the default dma address
*
*	move in the command tail
*	------------------------
	move.l	a1,a2		* save a pointer to the count field
        add.l   #$01,a1         * point past count field
        move.l  _tail,a0        * point to command tail
	clr.l	d0		* clear out d0
mvtail: cmpi.b	#$00,(a0)	* check for a NULL ending byte
	beq	done		* NULL byte terminates command
	cmpi.b	#$21,(a0)	* check for an '!'
	beq	done		* '!' ends the command
	move.b  (a0)+,(a1)+     * move a byte of the command tail
	addq	#1,d0		* bump up the character count
	bra	mvtail		* continue byte move
done:	move.b	d0,(a2)		* put in the character count
	move.b  #$00,(a1)	* terminate cmd tail with a NULL byte
*
*	fill fcb1 & fcb2
*	----------------
	move.l  #_cmdfcb,-(sp)  * put address of fcb buffer onto stack
	move.w	#1,-(sp)	* put 1 on stack(parm1)	
	jsr   	_fill_fcb	* jump to 'C' code & fill cmdfcb with parm1
	add.l	#6,sp		* clean off the stack
	clr.l	d0		* clear register d0
	moveq	#$5c,d0		* put basepage address of fcb1 in d0
	bsr     movfcb		* put fcb1 in the basepage
	move.l	#_cmdfcb,-(sp)	* put address of fcb buffer onto stack
	move.w	#2,-(sp)	* put 2 on stack(parm2)
	jsr	_fill_fcb	* jump to 'C' code & fill cmdfcb with parm2
	add.l	#6,sp		* clean off the stack
	clr.l	d0		* clear register d0
	moveq   #$38,d0		* put basepage address of fcb1 in d0
	bsr	movfcb		* put fcb2 in the basepage
*
*	now push rte stuff on stack
*	---------------------------
	movea.l	usrstk,a0	* get user stack pointer
	move.l	baspag,a1	* get basepage address
	move.l	8(a1),-(sp)	* push address we want to jump to
	move	sr,d0		* get the status register in d0
	andi	#$5f00,d0	* mask trace,system bits,user flags
	move.w  d0,-(sp)	* push it on stack
	move.l	a1,-(a0)	* push addr of basepage onto user stack
	move.l  #cmdrtn,-(a0)   * push return address onto user stack
	move.l  a0,usp		* set up user stack pointer
	rte
*
*	load error
*	----------
lderr:
	rts			* return with error code in d0
cmdrtn:
	move	#reboot,d0	* reboot CPM
	trap	#2
movfcb:
	add.l	baspag,d0	* get offset into basepage 
	move.l	d0,a0		* move address into a0
	move.l  #_cmdfcb,a1	* a1 points to fcb to be moved
	clr.l	d0		* clear register d0
	moveq	#35,d0		* get length of fcb
mov1:
	move.b  (a1)+,(a0)+	* move a byte into the basepage
	dbf	d0,mov1		* if not done branch to mov1	 	
	rts


	.bss

	.even
*
* LOAD PARAMETER BLOCK
*
LPB:	 .ds.l	 1
lowadr:  .ds.l   1
hiadr:   .ds.l   1
baspag:  .ds.l   1
usrstk:  .ds.l   1
flags:   .ds.w   1

*
* TPA Parameter Block
*
	.even
TPAB:	.ds.w	1
low:	.ds.l	1
high:	.ds.l	1











	.end
