; RESUPD - Update module in RES: (new must be same size or smaller than old)
; (C)1988 By Ami Bar-Yadin.
;       AMUS ID: AMI/AM
;
; Syntax:       RESUPD[/C] <filename>
;       default extension is .LIT
; SWITCHES:     C       Chop file to fit RES: module
;
;       loads file named into RES: overlaying module with same name.
;       if module named is not alread in RES:, program aborts.
;       if file named is larger than module, program aborts.
;       if file named is smaller than module, in will be NULL padded at end
;
;       the file named is loaded into MEM: first, so there must be enough
;       memory in the user's partition.  if there isn't the program aborts.
;       also space is needed in MEM: for the NULL pads mentioned above.
;
;       since the MEM: module might be expanded (NULL padding), and to be
;       able to locate the RES: module, the file must not exists in MEM:.
;       if it does, the program aborts
;
;       the actual overwriting to RES: is done in SUPERVISOR mode
;       with JLOCK / SVLOK.
;
;

VEDIT=102

;
; All commercial rights reserved, etc.
;
; If you want to include this program with a commercial package,
; go right ahead so long as you include the UNCHANGED source (.m68) with it.
;
; No warranties and/or guarranties of any kind, etc.
;
; Not responsible for damages resulting from the use of this program, etc.
;
; My employer (United Fashions) has nothing to do with this program and
; should not be blamed for it.
;
; I can be reached at:
;               United Fashions of Texas, Inc.
;               200 Ash Ave.
;               McAllen, TX  78501
;               (512) 631-2277/2276
;               8am-6pm
;
       SYM
       SEARCH  SYS
       SEARCH  SYSSYM
       RADIX   16.
       DEFAULT VEDIT,1
       DEFAULT $$MFLG,PV$RSM!PV$WSM
       DEFAULT $$SFLG,PH$REE!PH$REU
       DEFAULT $$LFLG,-1
       PHDR    $$LFLG,$$MFLG,$$SFLG


CR      =       13.


; some macros

DEFINE IMPINI  START
       DSECT
       IF B,START,     .=0
       IF NB,START,    .=START
ENDM
                               ; define label
DEFINE IMPDEF  LBL,SIZE
       IF NB,SIZE
LBL:    BLKB    SIZE
       IFF
LBL:    BLKB    0
       ENDC
ENDM
                               ; define size label
DEFINE IMPSIZ  LBL
       IF NB,LBL
LBL:
       ENDC
       PSECT
ENDM


DEFINE  IMPGET  SIZE,IDX,NOMEM,MODNM1,MODNM2,MODEXT
       PUSH    SIZE            ;(MAC:SYS.M68:  PUSH #SIZE)
       PUSH
       GETMEM  @SP
       IF      B,NOMEM
       BEQ     10$$
       EXIT
   10$$:
       IFF
       JNE     NOMEM
       ENDC
       POP     IDX
       POP
       IF      NB,MODNM1,      MOVW    #[MODNM1],M.NAM-ZID(IDX)
       IF      NB,MODNM2,      MOVW    #[MODNM2],M.NAM+2-ZID(IDX)
       IF      NB,MODEXT,      MOVW    #[MODEXT],M.EXT-ZID(IDX)
       ENDM
                               ; allocate memory

; start of code


RESUPD:
       GETIMP  SIZIMP,A5,,RES,UPD,IMP  ; allocate impure storage

       BYP
       LIN
       JEQ     HELP                    ; display help if no arguments

       CMPB    @A2,#'/
       BNE     0$
       INC     A2
       CMPB    (A2)+,#'C
       JNE     HELP
       MOV     #1,CHOPF(A5)
0$:
       FSPEC   DDB(A5),LIT             ; get file spec

       CALL    FNDMOD                  ; find RES: module, abort if not found

       CALL    GETFIL                  ; load file to MEM:, abort if can't

       MOV     MEMSIZ(A5),D1
       CMP     D1,RESSIZ(A5)
       BEQ     2$                      ; OK if file = RES: module size
       BLO     1$                      ; pad if file < RES: module size
       TST     CHOPF(A5)               ; Chop mode enabled?
       JEQ     ERR4                    ; abort if RES: module < file size
       BR      2$                      ; copy with chop
1$:     CALL    PADMEM                  ; extend MEM: to match RES:
2$:     CALL    OVERLY                  ; overlay MEM: onto RES:
       TYPE    <RES: >
       OFILE   DDB(A5),OT$TRM!OT$OFN
       TYPE    < module updated from >
       OFILE   DDB(A5),OT$TRM
       CRLF
       EXIT

FNDMOD:
       SRCH    D.FIL+DDB(A5),A0,0      ; search for memory module
       JNE     ERR1                    ; abort if module not found
       USRBAS  A1                      ; get start of user's memory
       CMP     A0,A1
       JHIS    ERR2                    ; abort if module is in MEM:
       MOV     A0,RESADR(A5)           ; save RES: module (DATA) address
       MOV     -ZID(A0),RESSIZ(A5)     ; save RES: module size (in bytes)
       RTN


GETFIL:
       FETCH   DDB(A5),A0,F.USR        ; load file into MEM:
       JNE     ERR3
       MOV     A0,MEMADR(A5)           ; save MEM: module (DATA) address
       MOV     -ZID(A0),MEMSIZ(A5)     ; save MEM: module size (in bytes)
       RTN


PADMEM:
       MOV     RESSIZ(A5),D1           ; get RES: module size in bytes
       MOV     MEMSIZ(A5),D2           ; get MEM: module size in bytes
       MOV     D1,D3                   ; D3 = RES: size(D1) - MEM: size(D2)
       SUB     D2,D3                   ; number of bytes needed to pad MEM:
       ADD     #8,D3                   ; need one Longword for terminating
                               ; MEM: modules chain, but I like to play safe
       USREND  D4                      ; address of last byte in MEM:
       USRBAS  D0                      ; address of first byte in MEM:
       SUB     D0,D4                   ; compute partition size
       JOBIDX                          ; adjust for command file size
       SUB     JOBCMZ(A6),D4           ; compute free memory available

       CMP     D4,D3
       JLO     ERR5                    ; abort if not enough memory for pad

       MOV     MEMADR(A5),A0           ; get MEM: module (DATA) address
       LEA     A1,-ZID(A0)             ; A1->MEM: module header
       PUSH    A1                      ; save module header address
       ADD     D2,A1                   ; A1->past MEM: module
                               ; next module (terminating NULL longword)
1$:     CLRB    (A1)+                   ; clear memory after MEM: module
       DBF     D3,1$
       POP     A1                      ; restore module header address
       MOV     D1,@A1                  ; set new size = RES: module size
       RTN


OVERLY:
       JLOCK                           ; suspend timesharing
       SUPVR                           ; enter SUPERVISOR mode
       SVLOK                           ; disable interrupts
                       ; DO OVERLAY
       MOV     RESADR(A5),A0           ; RES: module (DATA) address
       MOV     RESSIZ(A5),D1           ; RES: module size
       SUB     #ZID,D1                 ; no need to copy module header
       MOV     MEMADR(A5),A1           ; MEM: module (DATA) address
       DEC     D1                      ; (FOR DBF)
1$:     MOVB    (A1)+,(A0)+             ; DO IT TO IT!
       DBF     D1,1$
                       ; OVERLAY DONE
       SVUNLK                          ; enabled interrupts
       LSTS    #0                      ; exit SUPERVISOR mode
       JUNLOK                          ; resume timesharing
       RTN


; ERROR MESSAGES

ERR1:   TYPE    <?Memory module >
       OFILE   DDB(A5),OT$TRM!OT$OFN
       TYPECR  < not found.>
       EXIT

ERR2:   TYPE    <?Memory module >
       OFILE   DDB(A5),OT$TRM!OT$OFN
       TYPECR  < is in MEM: instead of RES:>
       EXIT

ERR3:   TYPE    <?File >
       OFILE   DDB(A5),OT$TRM
       TYPECR  < could not be loaded into user's (MEM:) memory.>
       TYPECR  <?(not enough memory, or file not found.)>
       EXIT

ERR4:   TYPE    <?File >
       OFILE   DDB(A5),OT$TRM
       TYPECR  < is larger than RES: module.>
       EXIT

ERR5:   TYPECR  <?Not enough memory in MEM: to pad module for RES: overlay>
       EXIT


HELP:   TTYI
       ASCII   "Syntax:        RESUPD[/C] filename"
       BYTE    CR,0
       EVEN
       TYPECR  <       default extension is .LIT>
       TYPECR  <SWITCHES:      C       Chop file to fit RES: module>
       EXIT
;
;
;
       IMPINI
       IMPDEF  DDB,D.DDB               ; DDB
       IMPDEF  RESADR,4                ; address of (old) module in RES:
       IMPDEF  RESSIZ,4                ; original size of module in RES:
       IMPDEF  MEMADR,4                ; address of (new) module in MEM:
       IMPDEF  MEMSIZ,4                ; size of disk file to be overlayed
       IMPDEF  CHOPF,4                 ; Chop mode flag

       IMPSIZ  SIZIMP
;
;
       END