; Program: SNAP ; Version: 1.0 ; Description: Save an image of the Z-system packages in a reloadable file. ; Syntax: SNAP file[.typ] ; Author: Rob Friefeld ; Date: 23 Dec 1987 ; Derivation: LAP by Bob Andersson (the idea, not the code) ; Assembly: SLR assembler ;SNAP captures an image of the ENV,IOP,RCP,FCP,NDR, WHEEL and PATH ;then writes the image, with a loader, to the file specified on the command ;line. When the output file is run, it puts the images back where they came ;from and calls the IOP initialization, if one is present. ; PROGRAM DEFINITIONS majver equ '1' minver equ '0' y equ -1 n equ 0 .accept 'Type 3 program to load at 8000h? (Y/N) ',hiload if hiload entry equ 8000h else entry equ 100h endif ; SYSTEM DEFINITIONS bdos equ 05h fcb1 equ 5ch wrconf equ 2 prbuff equ 9 openf equ 15 closef equ 16 srchff equ 17 erasef equ 19 writef equ 21 makef equ 22 setdmaf equ 26 sguserf equ 32 lf equ 0ah cr equ 0dh ; PACKAGE OFFSETS IN ENV rcpoff equ 0ch ;RCP iopoff equ 0fh ;IOP fcpoff equ 12h ;FCP envoff equ 1bh ;ENV expoff equ 09h ;PATH ndroff equ 15h ;NDR whloff equ 29h ;WHL ;============================================================================== ; ; S N A P C O D E ; ;============================================================================== org entry jp start db 'Z3ENV' db 3 z3eadr: dw 0fe00h dw entry ; ; TAKE A SNAPSHOT OF MEMORY ; start: di ld de,image+[cim-load] ; Buffer for core image ld bc,envoff ; ENV offset call getseg ; Save the segment ld bc,rcpoff ; RCP call getseg ld bc,iopoff ; IOP call getseg ld bc,fcpoff ; FCP call getseg snap1: ld bc,ndroff ; NDR call getseg1 jr z,snap2 ; No NDR snap01: ld bc,18 ; 18 byte entries ldir dec a jr nz,snap01 ldi ; NDR size = (Z3NDIRS*18)+1 snap2: ld bc,expoff ; PATH call getseg1 jr z,snap3 ; No path add a ; # 2 byte entries * 2 inc a ; Path size = (EXPATHS*2)+1 ld c,a ld b,0 ldir snap3: ld bc,whloff ; WHL call getseg1 ld bc,1 ldir ei ld (imagetop),de ; Save top of buffer pointer ; ; SET UP THE OUTPUT FILE ; ld a,(fcb1+1) ; Was it specified? cp ' ' jr z,oops ; No cp '/' jr z,oops ld hl,fcb1+9 ; Check .TYP ld a,(hl) cp ' ' jr nz,snap4 ; Specified ld (hl),'C' ; Make default .COM type inc hl ld (hl),'O' inc hl ld (hl),'M' snap4: ld a,(fcb1+13) ; Log in destinaton user ld e,a ld c,sguserf call bdos ld c,srchff ; Look for file call bdosde inc a jr z,onward ; Not there ld de,existmsg ; File exists. Erase Y/n ? ld c,9 call bdos ld c,1 call bdos and 5fh cp 'N' ret z ; Exit on NO ld de,crlf ld c,9 call bdos ld c,erasef ; Erase the file call bdosde onward: ld c,makef call bdosde ; ; WRITE THE OUTPUT FILE ; ld de,image ; Start of saved image wrtloop: push de ; DMA address ld c,setdmaf call bdos ld c,writef ; Write a record call bdosde pop de ; Inc DMA to next ld hl,128 add hl,de ex de,hl ld hl,(imagetop) ; Stored end of image xor a sbc hl,de jr nc,wrtloop ; Not past end yet ld c,closef call bdosde ld de,exitmsg ld c,prbuff jp bdos ; Exit program ; ; MESSAGES ; exitmsg: db ' Done$' oops: ld de,oopsmsg ld c,9 jp bdos oopsmsg: db 'SNAP, Ver ',majver,'.',minver,cr,lf db ' Syntax: SNAP file[.typ]$' existmsg: db 'File Exists. Replace? (Y/n) $' crlf: db cr,lf,'$' ; ; SUBROUTINES ; bdosde: ld de,fcb1 jp bdos ; Fetch a segment getseg: call getseg1 ; Set pointers ret z ; Zero size segment getseg01: ld bc,128 ; Move A records ldir dec a jr nz,getseg01 ret getseg1: ld hl,(z3eadr) ; Start of ENV add hl,bc ; Offset to segment ld a,(hl) ; Address of seg to HL inc hl push hl ld h,(hl) ld l,a pop bc inc bc ; Size of seg at BC ld a,(bc) ; Now in A or a ret imagetop: dw 0 image: ;============================================================================== ; ; O U T P U T F I L E C O D E ; ;============================================================================= .phase entry load: jp load1 db 'Z3ENV' db 3 lenvadr: dw 0fe00h dw entry ; ; LOADER ; load1: di ld de,cim ; Start of segment images, ENV first ld bc,envoff ; Make sure ENV is where image expects it call putseg1 ; HL -> ENV address of image ld bc,(lenvadr) ; BC -> current ENV xor a sbc hl,bc jp nz,loaderr ; They differ ld bc,envoff ; ENV call putseg ld bc,rcpoff ; RCP call putseg ld bc,iopoff ; IOP call putseg ld bc,fcpoff ; FCP call putseg load01: ld bc,ndroff ; NDR call putseg1 jr z,load02 ex de,hl load011: ld bc,18 ; 18 byte entries ldir dec a jr nz,load011 ldi ; NDR SIZE = (Z3NDIRS*18)+1 ex de,hl load02: ld bc,expoff ; PATH call putseg1 or a ; # 2 bytes entries jr z,load03 add a ; x 2 inc a ld c,a ld b,0 ex de,hl ldir ex de,hl load03: ld bc,whloff ; WHL call putseg1 ld bc,1 ex de,hl ldir call iopinit ; Init the IOP, if any ei ld de,loadmsg ; Tell user we are done ldprt: ld c,prbuff jp bdos ; Exit program loadmsg: db 'System Loaded$' loaderr: ld de,lderrmsg jr ldprt lderrmsg: db 'Wrong System$' ; Put a segment putseg: call putseg1 ; Pointer in HL ret z ; Zero size segment ex de,hl putseg01: ld bc,128 ldir dec a jr nz,putseg01 ex de,hl ret putseg1: ld hl,cim ; Start of ENV image putseg11: add hl,bc ; Offset to segment ld a,(hl) ; Address of seg to HL inc hl push hl ld h,(hl) ld l,a pop bc inc bc ; Size of seg at BC ld a,(bc) ; Now in A or a ret ; Initialize IOP iopinit: ld hl,(lenvadr) ; Get pointer to IOP base ld bc,iopoff call putseg11 ret z ; No IOP ld bc,9 ; Offset to INIT vector add hl,bc jp (hl) ; Run the routine ; ; CORE IMAGE SAVED BY SNAP ; cim: equ $ .dephase END START