; ************************** AMUS Program Label ******************************
; Filename: SYSLOD.M68                                      Date: 01/22/90
; Category: UTIL         Hash Code: 236-224-245-646      Version: 1.1(101)
; Initials: ULTR/AM      Name: DAVID PALLMANN
; Company: ULTRASOFT CORPORATION                   Telephone #: 5163484848
; Related Files: SEARCH.HLP; WLDSCN.LIB (required for assembly/linkage)
; Min. Op. Sys.: AMOSL 1.3B                    Expertise Level: BEG
; Special: Requires the 2.0 Assembler
; Description: Just like the SYSTEM command, but supports wildcarding.
; In system initialization file, useful for loading groups of files at a time
; for example  .SYSLOD BAS:*.RUN   or  .SYSLOD WRT:*.OVR
; ****************************************************************************

;****************************************************************************
;*									    *
;*				   SYSLOD				    *
;*		   Wildcard version of the SYSTEM command		    *
;*									    *
;****************************************************************************
;Copyright (C) 1989 UltraSoft Corporation.  All Rights Reserved.
;
;Written by: David Pallmann
;
;Donated to AMUS 22-Dec-89
;
;Edit History:
;1.0(100)  22-Dec-89  created. /DFP
;1.1(101)  22-Jan-90  optimized; now about 50% faster.  /DFP

	VMAJOR	=1
	VMINOR	=1
	VSUB	=0
	VEDIT	=101.
	VWHO	=0

	SEARCH	SYS
	SEARCH	SYSSYM

;wildcard scanner macros

DEFINE	WINIT
	IF	NDF,W.INIT,EXTERN W.INIT
	CALL	W.INIT
	ENDM

DEFINE	WSPEC	EXT
	IF	NDF,W.SPEC,EXTERN W.SPEC
	CALL	W.SPEC
	IF	B,EXT,ASCII /???/
	IF	NB,EXT,ASCII /'EXT/
	BYTE	0
	ENDM

DEFINE	WSCAN
	IF	NDF,W.SCAN,EXTERN W.SCAN
	CALL	W.SCAN
	ENDM

DEFINE	WFULL
	IF	NDF,W.FULL,EXTERN W.FULL
	CALL	W.FULL
	ENDM

DEFINE	WLIST	ADDR
	IF	NDF,W.LIST,EXTERN W.LIST
		IF	NB,ADDR
		PUSH	A0
		LEA	A0,ADDR
		ENDC
	CALL	W.LIST
		IF	NB,ADDR
		POP	A0
		ENDC
	ENDM

;variables

	.OFINI
	.OFDEF	FILE,	D.DDB		; file DDB
	.OFSIZ	MEMSIZ

;***********
;*  START  *
;***********
;Start of program

START:	PHDR	-1,PV$RSM!PV$WSM,PH$REE!PH$REU; program header
	GETIMP	MEMSIZ,A5		; allocate memory for variables

;see if we are already booted - if so, refuse to execute

CHKUP:	MOV	SYSTEM,D7		; get system bits
	ASR	D7			; check system-up bit
	JCS	SYSUP			;   it's already up - jump

;***********
;*  SETUP  *
;***********
;Set up for processing

SETUP:	INIT	FILE(A5)		; allocate buffer for file DDB
	WINIT				; initialize wildcard scanner, set A4

;**********
;*  SPEC  *
;**********
;process wildcard file specification

SPEC:	BYP				; bypass spaces/tabs
	LIN				; empty command line?
	JEQ	USAGE			;   yes - explain usage
	WSPEC	LIT			; process specification
	JNE	EXIT			;   rejected by WLDSCN

;***********
;*  FLOOP  *
;***********
;main processing loop - get next file from scanner and load it into system
;memory

FLOOP:	CTRLC	EXIT			; ^C check
	WSCAN				; get next file
	JNE	MORE			;   no more files
	LEA	A6,FILE(A5)		; index file DDB
	MOVW	D.DEV(A4),D.DEV(A6)	; set device code
	MOVW	D.DRV(A4),D.DRV(A6)	; set drive number
	MOV	D.FIL(A4),D.FIL(A6)	; set filename
	MOVW	D.EXT(A4),D.EXT(A6)	; set extension
	MOVW	D.PPN(A4),D.PPN(A6)	; set PPN
	CLR	D.DVR(A6)		; clear driver address

;**********
;*  OPEN  *
;**********
;open file and load it into system memory

OPEN:	LOOKUP	FILE(A5)		; look-up the file
	BNE	FLOOP			;   not found (not supposed to happen)
	TYPESP	Loading			; say we are loading
	PFILE	FILE(A5)		;   the file
	CRLF				; newline
	OPENI	FILE(A5)		; open for input
	MOV	SYSBAS,A1		; get base of system memory chain

;************
;*  LOCATE  *
;************
;Locate end of system memory module chain

LOCATE:	TST	@A1			; end of memory chain?
	BEQ	ADD			;   yes
	ADD	@A1,A1			; point to next module in chain
	BR	LOCATE			; loop

;*********
;*  ADD  *
;*********
;Add new module to system memory chain

ADD:	MOV	A1,A3			; copy module base
	ADD	#12.,A3			; account for size
	MOV	#12.,D5			;   of housekeeping header

;*********
;*  GET  *
;*********
;Get next byte from file and store in module

GET:	CTRLC	CLOSE			; ^C check
	CALL	GET.BYTE		; get next byte			[101]
	BNE	CLOSE			;   end of file - branch	[101]
	MOVB	D1,(A3)+		; store byte in memory
	INC	D5			; increment byte count
	BR	GET			; loop

;***********
;*  CLOSE  *
;***********
;Close file, finish up module

CLOSE:	CLOSE	FILE(A5)		; close file
	MOV	D5,D7			; copy module size
	AND	#1,D7			; is size odd?
	BEQ	10$			;   no
	INC	D5			;   yes - add one
	CLRB	(A3)+			;         to make it even
10$:	MOV	D5,(A1)+		; store size
	MOVW	#PRM!LOK!FGD,(A1)+	; store flags
	MOV	FILE+D.FIL(A5),(A1)+	; store filename
	MOVW	FILE+D.EXT(A5),(A1)+	; store extension
	CLR	(A3)+			; mark end of next module
	MOV	A3,MEMBAS		; set new MEMBAS
	JMP	FLOOP			; go handle next file

;**********
;*  MORE  *
;**********
;Done loading file - see if there is more on the command line
;If a comma is present we bypass it and go process another file specification

MORE:	BYP				; bypass spaces/tabs
	CMPB	(A2)+,#<',>		; comma here?
	JNE	EXIT			;   no - we are all done
	INC	A2			;   yes - skip it
	BYP				; bypass spaces/tabs
	JMP	SPEC			; go process filespec

;***********
;*  USAGE  *
;***********
;Explain how to use SYSLOD

USAGE:	TYPECR	<Usage: .SYSLOD files>	; tell all
	CRLF				; newline

EXIT:	EXIT				; exit

;***********
;*  SYSUP  *
;***********
;Tell user we can only be run at boot time

SYSUP:	TYPECR	The SYSLOD command may only be used during system initialization
	CRLF				; newline
	BR	USAGE			; also explain command syntax

;**************
;*  GET.BYTE  *
;**************
;Function:	Read next byte from FILE(A5)
;
;Inputs:	A3 - address of a file DDB, opened for sequential input
;
;Outputs:	D1 - low order byte contains data; all other bytes cleared
;		Z  - set if character received; 0 on error or end-of-file
;		N  - set if an error occurred

GET.BYTE:
	SAVE	A3,A6			; save registers
	LEA	A3,FILE(A5)		; index DDB
	CLR	D1			; pre-clear D1
	MOV	D.IDX(A3),A6		; pick up buffer index
	CMP	A6,D.SIZ(A3)		; check for buffer empty
	BLO	20$			;   not yet
	INPUT	@A3			; input next record
	MOVB	D.ERR(A3),D7		; error?
       	BNE	30$			;   yes
	MOV	D.IDX(A3),A6		; did we get anything?
	CMP	A6,D.SIZ(A3)		; end of file?
	BNE	20$			;   no
	REST	A3,A6			; restore registers
	LCC	#0			; clear Z, clear N (end of file)
	RTN				; return
20$:	ADD	D.BUF(A3),A6		; add buffer base
	MOVB	@A6,D1			; return the character in D1
	INC	D.IDX(A3)		; increment the index
	REST	A3,A6			; restore registers
	LCC	#PS.Z			; set Z, clear N (normal return)
	RTN				; return
30$:	REST	A3,A6			; restore registers
	LCC	#PS.N			; clear Z, set N (error)
	RTN				; return

	END