TITLE "NZBLITZ - SAVE/LOAD NZCOM SYSTEM IN BINARY" ;********************************************************** ; NZBLITZ ; Save NZCOM system image as COM file with loader. The ; saved image starts at the base address of the CCP (or ; optionally at the lowest RSX in memory if RSXOKF is true) ; and saves the entire OS up to (and optionally including) ; the CBIOS and, optionally, up to top of memory. This ; will save the ENV, Shell stack, Error handler, MCL, etc. ; ; This program consists of two separate parts. The first ; part is the system saver. The second part, located ; between .PHASE and .DEPHASE instructions, is the system ; loader. The loader segment is saved off as part of the ; system image COM file. ; ; Thanks to Joe Wright, for challenging me to write NZBLITZ ; and Carson Wilson for his suggestions for improvement. ; ; Copyright 1989,90 by Cameron W. Cotrill - All rights reserved. ; Released to the public domain for non-commercial use. ;********************************************************** ; ; Version 1.4 ; Shortened code for handling pending commands in MCL by 24 bytes. The ; loader is just under 1k again. Also fixed a label conflict that was ; causing problems for some assemblers. ; - Howard Goldstein 06/16/91 ; Revised top_of_save flag and code to allow ZCNFG to toggle through 3 ; top_of_save options: CBIOS, top_of_memory and specified top_of_save ; address. Revised calculation for number of image records, as it was ; causing the wrong number of records to be saved in certain situations. ; Corrected top_of_memory address to 0000h from FFFFh, as we save up to, ; not up through, an address. ; - Terry Hazen 06/18/91 ; ; Version 1.3 - Terry Hazen 06/06/91 ; The loader NZCOM.CCP FCB user/drive/filename is now copied directly ; from the NZBIOS NZCOM.CCP FCB user/drive/filename. The NZCOM.CCP ; file produced by the loader now automatically matches the the NZBIOS ; NZCOM.CCP specification in case it has been customized in the NZBIOS. ; The loader file now saves any pending multiple command line existing ; in the old system before loading the new system and appends it to the ; loader MCL, allowing us to include loader files in aliases - a very ; nifty feature. Thanks to Bob Dean and Biff Bueffel for the ; suggestions! ; ; Version 1.2 - Terry Hazen 05/28/91 ; Added code to get NZCOM.CCP user number from the NZBIOS. This is ; where NZCOM sets it. Thanks to Biff Bueffel for bringing up the ; user area question and Joe Wright for clarifying it. Changes are ; in lower case. ; ; Version 1.1 - Terry Hazen 05/25/91 ; Added ZCNFG configuration area with ZCNFG flag to allow saving up to ; CBIOS or up to address specified in SAVE (thanks to Howard Goldstein ; for the suggestion), SYSF flag to allow making NZCOM.CCP a system ; file and ARCF flag to allow making NZCOM.CCP an archived file. ; Changes are in lower case. ; VERS EQU 14 ; ; equates no equ 00h yes equ 0ffh ; ; ASCII EQUATES: BELL EQU 07H CR EQU 0DH LF EQU 0AH TAB EQU 09H ; ; DOS EQUATES: BOOT EQU 0 ; Warm boot vector IOBYTE EQU BOOT+3 ; Io redirection byte CUSER EQU BOOT+4 ; Current user number BDOS EQU BOOT+5 ; Bdos vector FCB1 EQU BOOT+5CH ; First fcb set by ccp FCB2 EQU BOOT+6CH ; Second fcb set by ccp DMABUF EQU BOOT+80H ; Default disk transfer (dma) buffer TPA EQU BOOT+100H ; Base of tpa ; ; DOS FUNCTION CODES: B$SRST EQU 0 ; Bdos system reset B$CONI EQU 1 ; Bdos read conole byte B$CONO EQU 2 ; Bdos write console byte B$RDRI EQU 3 ; Bdos read reader byte B$PUNO EQU 4 ; Bdos write punch byte B$LSTO EQU 5 ; Bdos write list byte B$DCIO EQU 6 ; Bdos direct console i/o B$GIOB EQU 7 ; Bdos get io byte B$SIOB EQU 8 ; Bdos set io byte B$OCS EQU 9 ; Bdos print console string B$ICS EQU 10 ; Bdos read console string B$RCS EQU 11 ; Bdos read console status B$GVER EQU 12 ; Bdos get cp/m version B$DRST EQU 13 ; Bdos disk system reset B$SELD EQU 14 ; Bdos select disk B$OPEN EQU 15 ; Bdos file open B$CLOS EQU 16 ; Bdos file close B$SCHF EQU 17 ; Bdos search for first name match B$SCHN EQU 18 ; Bdos search for next name match B$ERA EQU 19 ; Bdos erase file B$RSEQ EQU 20 ; Bdos read sequential B$WSEQ EQU 21 ; Bdos write sequential B$CRAT EQU 22 ; Bdos create file B$REN EQU 23 ; Bdos rename file B$GAD EQU 24 ; Bdos get active disks B$GCD EQU 25 ; Bdos get current (default) disk B$SDMA EQU 26 ; Bdos set disk buffer (dma) address B$GALV EQU 27 ; Bdos get allocation vector B$SDRO EQU 28 ; Bdos set disk to read only B$GDRO EQU 29 ; Bdos get read only disks B$SFA EQU 30 ; Bdos set file attributes B$GDPB EQU 31 ; Bdos get disk parameter block address B$USER EQU 32 ; Bdos get/set user number B$RRAN EQU 33 ; Bdos read random B$WRAN EQU 34 ; Bdos write random B$GFS EQU 35 ; Bdos get file size B$SRR EQU 36 ; Bdos set random record number B$RSTD EQU 37 ; Bdos reset drive B$WRZF EQU 40 ; Bdos write random with zero fill ; JP START Z3ST: DEFB 'Z3ENV' DEFB 1 ENVADR: DEFW 0 ; ; Configuration area ; RSXOKF: db yes ; Yes to save RSXs ; ; ZCNFG toggles this flag through all 3 choices. ; Select only ONE as the default: ; top: db 00000001b ; Save to CBIOS ;db 00000010b ; Save to top of memory ;db 00000100b ; Save to address in (save) ; db 'NZBLTZ' ; Default CFG filename db vers/10+'0',vers mod 10+'0' db 0 ; Termination ; sysf: db no ; YES to make NZCOM.CCP a system file arcf: db no ; YES to make NZCOM.CCP an archived file save: dw 0 ; Save to this address if TOP=100b ; (0000h=top of memory) ; START: LD HL,(ENVADR) LD (ENV),HL ; Save in loader while handy LD A,H OR L ; Test if any env JP Z,BARF PUSH HL LD DE,SIGNON CALL PRSTR XOR A LD (ERFLG),A ; No errors - yet ; VALIDATE ENV PASSED TO US IN HL INC HL INC HL INC HL ; Point to z3env message in env LD B,5 LD DE,Z3ST START1: LD A,(DE) ; Get local char to compare CP (HL) ; See if we were passed env pointer INC HL INC DE ; Bump pointers JP NZ,BARF ; Gag if we didn't (can't be nzcom) DJNZ START1 LD A,(HL) ; We have env, see if extended type RLCA ; By rolling msb into carry JP NC,BARF ; If no extended env, than no nzcom ; FOLLOWING CODE IS JOE WRIGHT'S NZCOM CHECK EXTRACTED FROM Z3LOC17 LD HL,(1) ; Get bios vector LD A,90-3 ; Offset to potential id ADD A,L LD L,A LD DE,NZCID ; Local id (below) LD B,6 ; Six bytes to check NZCHK: LD A,(DE) ; Get the byte at (de) CP (HL) ; Compare it with (hl) JP NZ,BARF ; Not nz-com INC DE INC HL ; Bump the pointers DJNZ NZCHK ; Next.. ; OK, WE HAVE A VALID ENV AND NZCOM IS RUNNING. ld de,ccusr ; Point to start of ccpfcb in loader ld bc,13 ; Copy nzbios fcb user/drive/filename ldir ; to ccpfcb ; LD A,(FCB1+1) CP ' ' ; Any file named? JP Z,HELP ; Show help if no file CP '?' ; This also means help JP Z,HELP CP '/' ; Zcpr style help? JP Z,HELP ; If in fcb1, must be... LD DE,FCB1+9 ; Point to file type in fcb LD HL,COM ; Point to file type LD C,3 ; B=0 from above LDIR ; Force com filetype ; SAVE SYSTEM ADDRESSES. LD HL,(1) LD (BIOSV),HL ; Save the bios vector LD HL,(6) LD (BDOSV),HL ; Likewise the bdos ; SET SAVE START ADDRESS TO LOWER OF CCP OR PROTECT POINTED TO BY 0006H LD IX,(ENVADR) LD E,(IX+3FH) LD D,(IX+40H) ; Put ccp address in de LD A,(IX+41H) LD (CCPBAS),DE ; Save in loader LD (CCPSIZ),A ; Save size too PUSH HL XOR A ; Clear the carry SBC HL,DE ; Test if any rsx's present POP HL JP C,RSXLOW ; Rsx present, so hl holds lower address EX DE,HL ; Else put address into hl RSXOK: LD (IBASE),HL ; Save as start address ; NOW SET TOP OF SAVE TO CBIOS (SAVE PATCH AREA ALSO - SPEEDS ZSDOS LOADS) EX DE,HL ; Save address in de ld hl,(sysf) ; Get system and archive flags ld (isys),hl ; Move them to loader file area ld a,(top) ; Get top of save flag ld l,0 LD H,(IX+2) ; Put cbios address in hl rra ; Save to CBIOS? jr c,sav ; Yes ; ld h,0 ; 0=top of memory rra ; Save to top of memory? jr c,sav ; Yes ; ld hl,(save) ; Else save to specified address ; sav: SBC HL,DE ; Calculate save size LD (IMGSIZ),HL ; Save for later LD B,H LD C,L PUSH BC ; Save image size EX DE,HL LD DE,SAVBUF ; Point to our save address LDIR ; Move the shooting match down to our buffer FILSAV: LD A,0FFH CALL GSUSER ; Get logged user LD (USER),A LD A,(FCB1+13) CALL GSUSER ; Set to fcb LD DE,FCB1 ; Point to fcb PUSH DE LD C,B$ERA ; Kill any file of same name CALL BDOS POP DE ; Restore fcb pointer LD C,B$CRAT CALL BDOS ; Create dest file ; pop hl ; Restore size in bytes ld bc,127 ; Calculate number of image records add hl,bc add hl,hl ld a,h add a,[SAVBUF-LOADER+127]/128 ; Plus loader records ld c,a ; BC=total file records ; LD DE,LOADER-80H ; Adjust for loader size ; ; SAVE LOOP ; FXFER7: LD A,B OR C ; Test store completed JR Z,FXFER8 ; If stored FXFE7A: LD HL,80H ADD HL,DE PUSH HL ; Save dma address EX DE,HL CALL SETDMA ; Point to next xfer area LD DE,FCB1 CALL FWRITE ; Write record POP DE ; Restore dma address JP NZ,WRERR ; Error - prob. disk full DEC BC ; Put another JR FXFER7 ; Do the next record FXFER8: CALL DSTCLO ; Close the destination file INC A ; Test for error JP Z,WRERR ; If there was one LD DE,OKMSG JR EXIT1 ; Print summary and exit ; ; WRITE ERROR HANDLER ; WRERR: OR 0FFH LD (ERFLG),A ; Show error CALL DSTCLO ; Close the destination LD DE,FCB1 LD C,B$ERA CALL BDOS ; Erase the file LD DE,WRTERM EXIT1: CALL PRSTR ; Print error message and exit LD HL,FCB1+1 LD B,11 EXIT2: LD A,(HL) AND 7FH ; Mask any attributes CALL CHAROT ; And display filename INC HL DJNZ EXIT2 LD A,(ERFLG) AND A ; Is this an error? LD DE,WRTER1 CALL NZ,PRSTR ; Print aborting message if so EXIT3: LD A,(USER) ; Get default user CALL GSUSER LD DE,CRLF CALL PRSTR ; Turn up a line and exit EXIT4: LD HL,(ENVADR) ; Get env pointer LD A,H OR L RET Z LD DE,18H ; Offset to mcl pointer ADD HL,DE LD A,(HL) INC HL LD H,(HL) LD L,A ; Now pointing to mcl base XOR A ; Get a cheap zero EX DE,HL LD L,4 ; H=0 from above ADD HL,DE ; Point to start of text on mcl EX DE,HL LD (HL),E INC HL LD (HL),D ; Reset mcl pointer to start of line INC HL ; Skip buffer length INC HL LD (HL),A ; Set char count to 0 INC HL LD (HL),A ; Null line RET ; ; HELP ; HELP: LD DE,HELPM ; Point to help message JR PERR1 ; Send it and exit ; ; ERROR HANDLERS ; RSXLOW: LD A,(RSXOKF) AND A JP NZ,RSXOK ; Don't trip error handler if ok to save LD DE,RSXERR ; Don't save rsx's JR PERR BARF: LD DE,NFGSYS PERR: OR 0FFH LD (ERFLG),A ; Indicate error CALL PERR1 ; Print why error CALL EXIT4 ; Cancel pending commands LD DE,ABORTM ; And inform we're aborting PERR1: LD C,B$OCS JP BDOS ; Print error message and quit RSXERR: DEFB BELL,'Can''t save with RSX''s loaded!$' NFGSYS: DEFB BELL,'Not ' NZCID: DEFB 'NZ-' COM: DEFB 'COM' DEFB ' system!$' SIGNON: DEFB 'NZBLITZ, Version ' DEFB VERS/10+'0','.',VERS MOD 10+'0',CR,LF,'$' HELPM: DEFB ' Saves running NZCOM system as .COM file. Any commands',CR,LF DEFB ' remaining on the ZCPR multiple command line will execute',CR,LF DEFB ' each time the program image is loaded.',CR,LF,LF DEFB 'Syntax:',CR,LF DEFB ' NZBLITZ [dir:]sysname[.com][;trailing;commands]',CR,LF,'$' WRTERM: DEFB BELL,'Disk write error ' WRTER1: DEFB ' -' ABORTM: DEFB ' Aborting!' CRLF: DEFB CR,LF,'$' OKMSG: DEFB ' System saved as $' ; ; UTILITY SUBROUTINES ; SETDMA: PUSH BC LD C,B$SDMA ; Set dma to de DOSCAL: PUSH DE DOSCA1: PUSH HL CALL BDOS ; Do bdos function call POP HL POP DE POP BC AND A ; Set flags to result RET ; CHAROT: PUSH BC LD C,B$CONO DOSCA2: PUSH DE LD E,A JR DOSCA1 ; FWRITE: PUSH BC LD C,B$WSEQ ; Sequential write JR DOSCAL ; DSTCLO: PUSH BC LD DE,FCB1 LD C,B$CLOS JR DOSCAL ; Close the destination file ; PRSTR: PUSH BC LD C,B$OCS JR DOSCAL ; Print string to console ; GSUSER: PUSH BC LD C,B$USER JR DOSCA2 ; ; RAM AREA ; USER: DEFB 0 ; Storage for default user number ERFLG: DEFB 0 ; Error flag PAGE ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; LOADER MODULE ; ; THIS SECTION IS WRITTEN OUT AS A STAND ALONE COM FILE ; AFTER THE SYSTEM IMAGE IS MOVED DOWN IMMEDIATELY ABOVE ; THIS MODULE. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; EQUATES SO SAVE ROUTINES CAN ACCESS HEADER OF LOADER ENV EQU $+0BH BIOSV EQU $+0DH BDOSV EQU $+0FH CCPBAS EQU $+11H CCPSIZ EQU $+13H IMGSIZ EQU $+14H IBASE EQU $+16H isys equ $+18h ; Flag offsets ccusr equ $+1ah ; User number offset LOADER: .PHASE 100H JP LDSTRT DEFB 'Z3ENV' DEFB 1 z3eadr: DEFW 0 ; Current system env address LENV: DEFW 0 ; Env storage address for sys to load LBIOSV: DEFW 0 ; Storage for location 1 LBDOSV: DEFW 0 ; Storage for location 5 LCCPBA: DEFW 0 ; Storage for ccp load address LCCPSZ: DEFB 0 ; Size of ccp in records LIMGSZ: DEFW 0 ; Image block size LDBASE: DEFW 0 ; Target address ldsys: db 0 ; System file flag ldarc: db 0 ; Archive file flag ; The CCP is saved to the following file. The NZBIOS NZCOM.CCP FCB ; (user/filename/drive) is copied directly on top of the filler ; defaults below. Any changes to the user/filename/drive, etc, ; must be made to the NZBIOS, and NZBLITZ will automatically follow ; merrily along! If you wish, you can use ZCNFG to configure NZBLITZ ; to set the saved NZCOM.CCP file system/archive attributes. ; Note that the CCPFCB format has been changed here to match the ; NZBIOS NZCOM.CCP FCB format for easier patching. ccuser: db 0 CCPFCB: DEFB 0 ; Drive to write CCP to (autoselect) DEFB 'nzcom ccp' DEFS 24,0 ; FIRST TASK IS TO SAVE NZCOM.CCP USING EXISTING SYSTEM LDSTRT: LD SP,100H ; Set stack up in a safe place LD DE,LSGNON CALL LPRSTR LD HL,(LCCPBA) LD DE,(LDBASE) XOR A SBC HL,DE ; Get relative offset to ccp in image LD DE,BUFFER-80H ; Get buffer start address ADD HL,DE ; Point to start of ccp PUSH HL ; Save start address ; LD A,0FFH CALL LGSUSR LD (LUSER),A ; Get current user CALL LGCD LD (LDRIVE),A ; And current drive LD A,(FCB1+1) CP '?' ; This means help JP Z,LHELP CP '/' ; Option? JR NZ,CPERA ; No, erase nzcom.ccp LD A,(FCB1+2) CP 'F' ; Fast? JP Z,LFAST JP LHELP ; Else help CPERA: LD A,(CCUSER) CALL LGSUSR ; Set user for write of ccp LD DE,CCPFCB ; Point to fcb PUSH DE LD C,B$ERA ; Kill any file of same name CALL BDOS POP DE ; Restore fcb pointer LD C,B$CRAT CALL BDOS ; Create dest file POP DE ; Get save address back LD A,(LCCPSZ) LD C,A LD B,0 ; Set record count ; ; SAVE LOOP ; CPSAV: LD A,B OR C ; Test store completed JR Z,CPSAV1 ; If stored LD HL,80H ADD HL,DE PUSH HL ; Save dma address EX DE,HL CALL LSTDMA ; Point to next xfer area LD DE,CCPFCB CALL LFWRT ; Write record POP DE ; Restore dma address JP NZ,LWRERR ; Error - prob. disk full DEC BC ; Put another JR CPSAV ; Do the next record CPSAV1: CALL LFCLOS ; Close the destination file INC A ; Test for error JP Z,LWRERR ; If there was one ; . . LD HL,CCPFCB+3 ; No datestamp attribute SET 7,(HL) ; ld hl,ccpfcb+10 ; Point to system attribute ld a,(ldsys) ; Save as system file? or a jr z,cpsav2 ; No set 7,(hl) ; Make it a system file cpsav2: ld a,(ldarc) ; Save file as archived? or a jr z,cpsav3 ; No inc hl ; Point to archive attribute set 7,(hl) ; Archive it cpsav3: LD C,B$SFA ; Set attributes CALL BDOS ; ; Save any existing mcl into temporary buffer ; LFAST: ld bc,0 ; Initialize counter/flag for pending mcl ld ix,(z3eadr) ; Point to current environment ld a,(ix+3) cp 'Z' ; Quick check for Z system jr nz,lfast0 ; Not Z system so skip mcl stuff ; ld l,(ix+18h) ; Get mcl address ld h,(ix+19h) call lhlhl ; Point to starting byte ld de,(ldbase) ; Get base of new system dec d ; Start mcl buffer 200h earlier dec d ld (mclbuf),de ; Save start of buffer call putcl ; Move mcl to temp buffer ; ; MOVE NEW SYSTEM INTO POSITION ; lfast0: push bc ; Save mcl char count/flag on stack LD HL,(LBIOSV) LD (1),HL ; Set warm boot address LD HL,(LBDOSV) LD (6),HL ; And bdos vector ; LD BC,(LIMGSZ) ; Get number of bytes to move LD DE,(LDBASE) ; And target address LD HL,BUFFER ; Where image is LDIR LD C,37 LD DE,0FFFFH ; Reset all hard drives CALL BDOS ; LD HL,(LENV) ; Get env address LD DE,22H ADD HL,DE call lhlhl ; Get message buffer address LD E,2EH ADD HL,DE ; Point to user LD A,(LUSER) LD (HL),A ; Save in message buffer CALL LGSUSR ; Restore user INC HL LD A,(LDRIVE) LD (HL),A ; Set drive in message buffer CALL LSETDK ; ; Append old mcl to our mcl ; pop bc ; Get pending command char count ld a,b or c jr z,lfast1 ; No buffer - no pending commands ; ld ix,(lenv) ; Point to mcl call getmcl ; HL pts to mcl, DE pts to buffer start push af ; Save buffer size on stack call lhlhl ; HL points to first command byte call putcl ; Slide command line to head of buffer pop af ; Restore mcl length dec b ; Check high byte of char count inc b jr nz,toobig ; Overflow if > 0 cp c ; Compare count to mcl length jr c,toobig ; ld hl,(mclbuf) ; Point to mcl buffer call putcl ; Move commands into mcl call getmcl ; HL pts to mcl, DE pts to buffer start ld (hl),e ; Initialize mcl pointer inc hl ld (hl),d jr lfast1 ; toobig: ld de,ovfl ; Display mcl overflow message call lprstr ; lfast1: LD A,(004H) ; Get logged du LD C,A ; Into c register for ccp LD HL,(LCCPBA) JP (HL) ; And exit to ccp (which does an f13) ; ; WRITE ERROR HANDLER ; LWRERR: CALL LFCLOS ; Close the destination LD DE,CCPFCB LD C,B$ERA CALL BDOS ; Erase the ccp file LD DE,LWRTRM LPRTXT: CALL LPRSTR ; Print error message and exit LD A,(LUSER) CALL LGSUSR ; Restore user LD A,(LDRIVE) CALL LSETDK JP 0 ; LHELP: LD DE,LHELPM ; Point to help message JR LPRTXT ; Print it and exit ; LSGNON: DEFB 'NZBLITZ loader vers ' DEFB VERS/10+'0','.',VERS MOD 10+'0',CR,LF,'$' LWRTRM: DEFB BELL,'Disk write error on NZCOM.CCP - aborting!',CR,LF,'$' LHELPM: DEFB ' This program contains a NZCOM operating system.',CR,LF DEFB ' The NZCOM system will replace the current system if',CR,LF DEFB ' the name of this file is typed with no arguments.',CR,LF,LF db ' When running in a ZCPR3 environment, pending commands',cr,lf db ' will be appended to the NZCOM multiple command line,',cr,lf db ' allowing the NZCOM system to be loaded as part of an',cr,lf db ' alias script.',cr,lf,lf DEFB ' If a single NZCOM system is always used, the /F option',CR,LF DEFB ' may be used to skip writing NZCOM.CCP.',CR,LF,'$' ovfl: db bell,'Command line overflow!',cr,lf,'$' ; ; UTILITY SUBROUTINES ; LSTDMA: PUSH BC LD C,B$SDMA ; Set dma to de LDOSCA: PUSH DE PUSH HL CALL BDOS ; Do bdos function call POP HL POP DE POP BC AND A ; Set flags to result RET ; LGCD: PUSH BC LD C,B$GCD ; Return current disk JR LDOSCA ; LSETDK: PUSH BC LD C,B$SELD JR LDOSC1 ; LFWRT: PUSH BC LD C,B$WSEQ ; Sequential write JR LDOSCA ; LFCLOS: PUSH BC LD DE,CCPFCB LD C,B$CLOS JR LDOSCA ; Close the destination file ; LPRSTR: PUSH BC LD C,B$OCS JR LDOSCA ; Print string to console ; LGSUSR: PUSH BC LD C,B$USER LDOSC1: LD E,A JR LDOSCA ; putcl: ld a,(hl) ; Move mcl ld (de),a or a ret z ; Quit at termination inc hl inc de ; Bump pointers inc bc ; Bump count jr putcl ; ; Returns HL=mcl pointer, DE=start of buffer, A=buffer size ; getmcl: ld l,(ix+18h) ; HL points to start of mcl ld h,(ix+19h) ld e,l ld d,h ; Pointer in DE also inc de inc de ld a,(de) ; Get buffer size inc de inc de ret ; lhlhl: ld a,(hl) ; Load hl with contents of hl inc hl ld h,(hl) ld l,a ret ; ; RAM AREA ; LDRIVE: DEFB 0 LUSER: DEFB 0 mclbuf: dw 0 ; Start of temporary mcl buffer BUFFER: .DEPHASE SAVBUF: END