; ************************** 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