.TITLE SAVOVR .IDENT \V02.03\ .SBTTL SAVOVR SAVE THE FILE ;++ ; FUNCTIONAL DESCRIPTION: ; This overlay actually does the work to SAVE the ; Workspace Core Image. ; ; INPUTS: ; R2 - Pointer to the (open) channel which will ; be used to read in the file ;-- .PSECT CODE SAVOVR:: POP R4 ;Save the Return Address TST C.BUFF(R2) ;ANY BUFFER? BEQ 1$ ;BETTER NOT BE! SYSERR ;OOPS 1$: PUSH SI ;Save the current SI value MOV SP,SPHOLD ;MARK WHERE SP STACK IS .IF GE RSTS ;+ ; First move stack into stack buffer. This buffer is located ; at the front of the variable overlay so that the buffer can be ; written out with the variables. ;- MOV SPINIT,R0 ;POINT TO HIGH END OF STACK SUB SP,R0 ;GET LENGTH OF STACK ; ASR R0 ;CONVERT TO WORD COUNT ROR R0 ;CONVERT TO WORD COUNT MOV #CPOUTL,R1 ;POINT TO STACK BUFFER MOV SP,R3 ;POINT TO LOW END OF STACK MOV R1,C.BUFF(R2) ;START OF BUFFER MOV #OBUFLN,C.BUFL(R2) ;Size of buffer 2$: MOV (R3)+,(R1)+ ;COPY STACK SOB R0,2$ ;VERY FAST! BIS #C.FLSH,C.SBIT(R2) ;MUST WRITE THIS OUT CALL WRITEB ;Output the Info .IFTF ;+ ; If the last block is free (and it usually will be), then ; we pretend it isn't there, allowing the file to be as ; small as possible, as well as having different configuations ; of APL (Memory only, not different as to with/without FPP, etc) ; be able to use the same Workspace. ;- MOV ENDCOR,R0 ;Get the end of space PUSH R0 ;Save the end pointer MOV -2.(R0),R1 ;Get the size of the last block BLE 3$ ;Block is allocated, never mind SUB R1,R0 ;Back up SUB R1,R0 ; (R1 is in words) MOV #4.,(R0)+ ;Fake small last frame CMP (R0)+,(R0)+ ;Skip linked list stuff MOV #4.,(R0)+ ;Top of last free frame MOV R0,ENDCOR ;Save it for save MOV #-1.,(R0) ;Top of core .IFT ;+ ; Now write free storage to file ;- 3$: TST (R0)+ ;Bump pointer up so size computes right SUB #SYSTAT,R0 ;Minus start of interpreter data MOV #SYSTAT,C.BUFF(R2) ;Point to start of data area 4$: BIS #C.FLSH,C.SBIT(R2) ;MUST WRITE THIS OUT CALL WRITEB ;WRITE OUT FREE STORAGE ADD C.BUFL(R2),C.BUFF(R2) ;Increment buffer pointer SUB C.BUFL(R2),R0 ;Subtract size of buffer CMP R0,#OBUFLN ;Any more whole blocks left? BHI 4$ ;Yes, Then loop some more TST R0 ;No, Any bytes left? BGT 5$ ;Yes SYSERR ;No, There should be, SYSTEM Error 5$: MOV R0,C.BUFL(R2) ;Number of bytes left in last block .IF NE RSTS MOV C.BUFF(R2),R0 ;Copy pointer to Source MOV #CPOUTL,R1 ;Pointer to destination MOV R1,C.BUFF(R2) ;Point to Buffer MOV C.BUFL(R2),R3 ;Count for block ; ASR R3 ; in words ROR R3 ; in words 6$: MOV (R0)+,(R1)+ ;Copy, word mode SOB R3,6$ ;Loop for all MOV #OBUFLN,R3 ;Size of Buffer SUB C.BUFL(R2),R3 ; minus what we've done ; ASR R3 ;Divide by 2 ROR R3 ;Divide by 2 BEQ 8$ ;Nothing happens here 7$: CLR (R1)+ ;Clear the rest of the buffer SOB R3,7$ ;Loop for each 8$: MOV #OBUFLN,C.BUFL(R2) ;Buffer Length .ENDC .IFF MOV ENDCOR ;Get Pointer to end of core ADD #,R0 ;Take ceiling BIC #,R0 ; for # of blocks MOV R0,C.BUFL(R2) ;Buffer Size CLR C.BUFF(R2) ;Start at CLR C.PTR(R2) ; beginning of region .ENDC BIS #C.FLSH,C.SBIT(R2) ;Must output block CALL WRITEB ;Write it out CALL RESCHN ;Reset the channel ;+ ; Finish up the save - restore the true WS size ;- POP R0 ;Get the true end pointer MOV -2.(R0),R1 ;Get size of last element BLE 9$ ;Must be allocated MOV R0,ENDCOR ;Point to end of core SUB R1,R0 ;Back up SUB R1,R0 ; (R1 in words) MOV R1,(R0) ;Restore the size of the last block 9$: POP SI ;Restore the SI value BIS #SY.SVL+SY.SRT,SYSTAT ;That's it, end special SAVE/LOAD mode JMP (R4) ;Finished, Return