TITLE "MYLOAD - Mload look-alike for ZCPR 3.x and NZ-COM" ;======================================================================== ; M Y L O A D - MLOAD for NZ-COM and ZCPR 3.x ;------------------------------------------------------------------------ ; This program was developed out of frustration with other MLOAD programs ; which are supposed to overlay COM files with HEX overlays. It senses ; an extended ZCPR3 Environment Descriptor and protects the CPR. This ; somewhat limits the size of files which can be handled, but operates ; faster in most cases. ; 29 August 1989 Harold F. Bower ; Revisions: ; 1.0a - 13 Dec 90 - corrected Zsystem initialization flow. HFB ;------------------------------------------------------------------------ ; The syntax for MYLOAD is: ; MYLOAD [dir][comfil[.com][=][dir][oldcom[.com]],[fir][fil1[.hex]],... ; If no destination file is specified, the name of the first input file ; is taken for the output file. If the first specified file is of type ; HEX, then a simple HEX load is assumed, followed by optional HEX over- ; lays. Addresses are validated to insure that no HEX file specifies an ; address less than 100H. ;======================================================================= VER EQU 10 ; First Test Version rev equ 'a' ; Bug fix version ;..... ; CP/M Equates WBOOT EQU 0 BDOS EQU 5 FCB EQU 005CH FCB2 EQU 006CH BUFF EQU 0080H ; Character and Miscellaneous Equates BELL EQU 07H CR EQU 0DH FF EQU 0CH LF EQU 0AH NO EQU 0 YES EQU NOT NO ; Set Public equates to "Fool" linkers into using BDOS instead of BIOS I/O PUBLIC COUT, COUT7 ; BOUT call will be COUT to SYSLIB routines ; From Z3LIB Get.. EXT Z3INIT, Z3LOG, WHRENV, ZPRSFN, GETQUIET, @SDELM, DUTDIR ; From SYSLIB Get.. EXT CODEND, RETUD, LOGUD, INITFCB, SETDMA EXT COMPBC, COMPHD, CIN, CAPS EXT EPRINT, BOUT, PFN2, CRLF, PAFDC, PHL4HC, PHLFDC EXT F$MAKE, F$OPEN, F$CLOSE, F$READ, F$WRITE, F$EXIST, F$DELETE ;===================================================================== ; S T A R T T H E P R O G R A M ;===================================================================== JP START ; Bypass header and start execution DEFB 'Z3ENV' ; This is a ZCPR3 Utility DEFB 1 ; External Environment Descriptor ENVADR: DEFW 0001 ; Set Non-zero to force search DEFW 0000 ; Filler for Type 4 Header DEFB 'MYLOAD ' ; Use this Configuration File w/ZCNFG ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; C o n f i g u r a t i o n S e c t i o n ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VERBOS: DEFB YES ; Set YES to be verbose, NO to be quiet USEBEL: DEFB YES ; Set YES to ring bell on Errors, Else NO ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Begin program Execution START: LD HL,OFCB ; Clear workspace RAM LD E,L LD D,H INC DE LD BC,STACK+1-OFCB LD (HL),0 LDIR LD (STACK),SP ; Save entry stack LD SP,STACK ; .and set up a local one CALL RETUD ; Get the current Drive and User LD (CUSER),BC ; ..and save locally LD HL,(BDOS+1) ; Get the BDOS entry address CALL WHRENV ; .and try to locate an ENV above there LD (ENVADR),HL ; ..save in header LD A,H OR L ; Set Zero Flag based on ENV presence LD A,(VERBOS) ; .get Verbose flag to set Quiet flag JR Z,NOENV ; ..bypass next checks if No Env ; Have a Z-System. Initialize Libraries and test for Extended Environment LD B,A ; Save the Verbose flag CALL Z3INIT ; If we have an ENV, Initialize Lib routines CALL GETQUIET ; .Get the Z-System Quiet Flag OR B ; ..add in the local flag LD (QUIET),A ; ...and save as the overall Quiet signal EX DE,HL ; Put ENV addr in DE LD HL,8 ; .and offset to Extended flag ADD HL,DE BIT 7,(HL) ; Is it Extended? JR Z,NOENV ; ..jump if not to calculate CPR Base LD HL,3FH ; Else offset to CPR Base addr ADD HL,DE ; Point to it LD E,(HL) ; .and retrieve INC HL LD D,(HL) EX DE,HL ; Move CPR Base addr to HL JR HAVBAS ; ..and jump to save it ; No Z3 Environment, calculate the base of CCP/CPR NOENV: LD (QUIET),A ; Since No Env, simply copy Verbos to Quiet LD HL,(WBOOT+1) ; Get Vector to BIOS WB vector LD DE,-1603H ; .set negative offset to CPR Base ADD HL,DE ; ..and calculate HAVBAS: EX DE,HL ; Put the results in DE LD HL,(BDOS+1) ; ..and see if RSX present CALL COMPHD ; Is CPR Base above BDOS vector? JR C,HAVRSX ; ..jump if so to save RSX entry vector EX DE,HL ; Else put CPR base addr back in HL HAVRSX: LD (TOPADR),HL ; Store the Base of OS (CPR or RSX) ; Copy Default Command Buffer to local storage to save Command Tail CALL CODEND ; Get base of Buffer space LD E,L ; .put to DE LD D,H INC H ; ..offset by one sector worth LD (BASADR),HL ; Save pointer to User base LD (WRKPTR),HL ; .as base of Work Area LD (TOPFIL),HL ; ..and as the top of Work Area LD HL,BUFF ; Point source to Default Buffer LD BC,128 LDIR ; ..and copy Command tail to buffer ; Everything basically set up. Initialize Terminal and print signon banner CALL EPRINT DEFB CR,LF,'MYLOAD',' Ver ',VER/10+'0','.',VER MOD 10 +'0',rev DEFB ' - by Harold F. Bower 13 Dec 90' DEFB CR,LF,LF,0 ; Check for Help Request LD HL,FCB+1 ; Point to first FCB LD A,(HL) CP '/' ; Is it a Help request? JP NZ,START0 ; ..jump if not HELP: CALL EPRINT DEFB 'Purpose: Load Hex File, or Overlay COM with HEX file(s)',CR,LF DEFB LF,' Syntax:',CR,LF DEFB ' (file specs may contain DU: or, with ZCPR3, DIR:)',CR,LF,LF DEFB ' MYLOAD // <-- Print this message',CR,LF DEFB ' MYLOAD prog <-- Load prog.HEX to prog.COM' DEFB CR,LF DEFB ' MYLOAD prog,prog1,.. ' DEFB '<-- Overlay prog.COM w/prog1.HEX',CR,LF DEFB ' or load prog.HEX then over-',CR,LF DEFB ' lay with prog1.HEX',CR,LF DEFB ' MYLOAD prog2=prog1,prog2,.. ' DEFB '<-- Overlay prog1.COM with',CR,LF DEFB ' prog2.HEX forming prog2.COM' DEFB 0 EXIT: CALL CRLF ; Give a New Line LD BC,(CUSER) ; Get Current Drive and User CALL LOGUD ; ..and restore LD SP,(STACK) RET ; Start program by printing some statistics START0: LD A,(QUIET) ; Operate Quietly? OR A JR Z,STRT0V ; ..don't print this if so CALL EPRINT DEFB ' Base of Output Buffer = ',0 LD HL,(BASADR) CALL PHL4HC CALL CRLF CALL EPRINT DEFB ' Top of Output Buffer = ',0 LD HL,(TOPADR) CALL PHL4HC CALL CRLF ; Give a couple of lines separation CALL CRLF ; Zero the entire buffer for "cleanliness" STRT0V: LD DE,(BASADR) ; Get Beginning of Buffer LD HL,(TOPADR) ; .and top address in Memory OR A SBC HL,DE ; ..then calculate the Buffer space LD C,L ; Move count to BC LD B,H LD L,E ; .and starting Addr to HL LD H,D DEC BC ; ..down one count INC DE ; ...and dest up one LD (HL),0 ; Set first byte to Zero LDIR ; ..and move it along LD DE,FCB ; Set up to parse the Command Tail CALL INITFCB ; .initialize the FCB CALL CODEND ; Get start of Command Tail INC HL ; ..bypassing the Count byte CALL SKWSP ; Skip over "White Space" JP Z,HELP ; ..jump to Help if No arguments XOR A ; .do DIR before DU CALL ZPRSFN ; Parse the next token PUSH HL ; ..save ptr to delimiter LD DE,OFCB ; .to the Output FCB CALL INITFCB ; ..initializing it first LD HL,FCB ; Move from this FCB LD BC,16 ; Move just first 16 bytes LDIR LD DE,OFCB+9 ; Check the Output file type LD A,(DE) ; Get the first char CP ' ' ; Anything entered? JR NZ,START1 ; ..accept specified type LD HL,COMTYP ; .against COM type string LD BC,3 CALL COMPBC ; ..and compare JR Z,START1 ; Jump if Same LDIR ; ..else move COM type START1: POP HL ; Restore pointer to delimiter LD A,(HL) ; .get the delimiter CP '=' ; Is an explicit output file specified? JR NZ,START2 ; ..bypass first HEX read if Not (default out) INC HL ; Else bypass equal sign CALL SKWSP ; .and bypass any space chars JR Z,START3 ; ..jumping to simple Load if EOL LD DE,FCB ; Set up to parse next file name XOR A ; .do DIR before DU CALL ZPRSFN ; Parse LD DE,OFCB+1 ; .point to first char of File Name LD A,(DE) CP ' ' ; Anything there? JR NZ,START3 ; ..jump if we have an output file name PUSH HL ; Else save input line pointer LD HL,FCB+1 ; .point to second file name LD BC,8 LDIR ; ..and move 8-char name POP HL ; Restore input line pointer JR START3 ; ..and continue on ; If we come here, same root name used for input and output. Set output ; file to current DU, and use specified one for source START2: LD BC,(CUSER) ; Get Current DU LD A,B ; Load Drive INC A ; .setting base 1..16 LD (OFCB),A ; ..save in Output FCB LD A,C ; Load User LD (OFCB+13),A ; .and save in Output FCB also ; Input and output files now all set up START3: LD (SCNPTR),HL ; Save pointer to scan line LD DE,FCB+9 ; Check for COM type of first Input file LD HL,COMTYP LD BC,3 CALL COMPBC ; Input file of type COM? JR Z,START4 LDIR ; ..else set it to COM ; See if the specified Input File exists as COM START4: CALL SRCHF ; Does the first file exist? JR Z,START5 ; ..jump if COM Not found to check HEX CALL OPENIN ; Else Open the file for Reading JP NZ,OPNERR ; ..Jump to error if Problem CALL LODMSG ; Print Loading message LD HL,(WRKPTR) ; Get Base address INPLOP: LD (WRKPTR),HL ; Save working ptr LD (TOPFIL),HL ; ..and top-of-file pointer CALL SETDMA ; Set the Transfer Address CALL RDSEC ; Read a sector there JR NZ,READY ; ..jump to close file if EOF or Error LD BC,128 ; Offset to next sector ADD HL,BC CALL CKOVFL ; Will we go too far? (abort on Err) JR INPLOP ; .loop if not ; See if the specified Input File exists as HEX START5: CALL QPRINT ; Space in a little DEFB ' ',0 INC DE LD A,(QUIET) OR A CALL NZ,PFN2 ; Print the file name if Not quiet DEC DE CALL QPRINT DEFB ' Not Found...changing to HEX..',CR,LF,0 LD HL,9 ; Advance to Type ADD HL,DE PUSH DE ; Save FCB pointer EX DE,HL LD HL,HEXTYP ; Point to HEX file type LD BC,3 LDIR ; ..and move type field POP DE ; Restore FCB pointer CALL SRCHF ; .and try to find Hex version JR NZ,START6 ; ..jump to continue if File Found CALL NFERR ; Else print error JP EXIT ; ..and abort START6: CALL OPENIN ; Else try to open it JP NZ,OPNERR ; ..abort with error if unable to open CALL LODMSG ; Else program exists..Announce it CALL RDHEX ; ..and Load the Hex file ; This is the main loop for loading overlays. loops here til done READY: CALL CLOSIN ; Close the Input file, restoring defaults READY0: LD DE,FCB CALL INITFCB ; Initialize the FCB for any overlay LD HL,(SCNPTR) ; Get pointer into argument line CALL SKWSP ; Scan for text JR Z,DONE ; ..jump to Closing code if no more XOR A CALL ZPRSFN ; Else parse the filename LD (SCNPTR),HL ; ..and save the delimiter address LD HL,9 ; Advance to Type ADD HL,DE LD A,(HL) ; Get the first char of Type CP ' ' ; Anything entered? JR NZ,HAVTYP ; ..jump if we have user-entered type PUSH DE ; Else save FCB pointer EX DE,HL LD HL,HEXTYP ; .Point to HEX file type LD BC,3 LDIR ; ..and move HEX type field POP DE ; Restore FCB pointer HAVTYP: CALL SRCHF ; Does the file exist? JR NZ,READY1 ; ..jump if Ok CALL NFERR ; Else print an error CALL RESTOR ; .restore defaults JR READY0 ; ..and back for more READY1: CALL OPENIN ; Try to open the file JP NZ,OPNERR ; ..jumping to error if a problem CALL OVLMSG ; Announce this file CALL RDHEX ; .then load the file JR READY ; ..and back for more ; All loading is done at this point. Finish up the effort DONE: CALL EPRINT ; Print another statistic DEFB CR,LF,' Done.',0 CALL QPRINT DEFB ' Saving ',0 LD HL,(TOPFIL) ; Calculate size of new image LD DE,(BASADR) OR A SBC HL,DE ; ..and Top of all loads JP Z,NULFIL ; Jump to Error Exit if No contents PUSH HL ; .(save) LD A,(QUIET) ; Print permitted? OR A CALL NZ,PHLFDC ; Print in decimal if so CALL QPRINT DEFB ' (',0 CALL QPRHEX ; ..and hex CALL QPRINT DEFB 'H) Bytes to : ',0 LD DE,OFCB CALL PRNAME POP HL ; Get the value back ; Now calculate the number of sectors to write LD A,L ; Get Low byte to A LD L,H ; Number of pages to L LD H,0 ; ..nulling Hi byte ADD A,A ; Shift MSB to Carry ADC HL,HL ; .Mult pages by 2 for records and shift ; ..Carry to LSB of L LD C,L ; Put record count in BC LD B,H OR A ; Partial page? JR Z,NOPART ; ..jump if not INC BC ; Else bump record count by one NOPART: LD DE,OFCB ; Now attempt to locate the file CALL SRCHF0 ; Does it exist? JR Z,DONE0 ; ..jump if not to make it ; A search for the file showed that it exists. Ask for replacement CALL RING ; File exists...wake up the operator CALL EPRINT ; ..then message DEFB ' +++ File Exists...Replace it? (Y/[N]) : ',0 CALL CIN ; Get the answer CALL CAPS ; ..in uppercase CALL COUT ; Echo it CALL CRLF ; ..and go to new line CP 'Y' ; Was it a YES? JP NZ,EXIT ; ..exit if Not CALL F$DELETE ; Else delete the file, fall thru to Make ; The Destination File does not exist. Create it and write the buffer. DONE0: CALL F$MAKE ; Create the file in current DU: INC A ; Any Error? (FF-->0) JP Z,MAKERR ; ..jump to error exit if No Dir space LD HL,(BASADR) ; Get the starting address OUTLOP: LD (WRKPTR),HL ; ..save top of file CALL SETDMA ; Set the Transfer Address CALL F$WRITE ; Write a sector from there JR NZ,DONE1 ; ..jump to close file if Error PUSH BC ; Save count LD BC,128 ; Offset to next sector ADD HL,BC POP BC ; restore count DEC BC ; Count down sector count LD A,B OR C ; Are we finished? JR NZ,OUTLOP ; ..loop if Not DONE1: PUSH AF ; Save status (0=Ok, else Error) CALL F$CLOSE ; .close the file (good or bad) POP BC ; ..and check for Close or Write errors OR B JR Z,DONEOK ; Jump if No errors CALL RING ; We had errors, notify operator CALL EPRINT DEFB ' +++ Write or Close Errors..Erasing file!',0 CALL F$DELETE JR EXITV ; ..and quit DONEOK: CALL EPRINT ; Give status DEFB ' ..Ok',0 EXITV: JP EXIT ; ..and exit properly ;--------------------------------------------------------------------------- ; U T I L I T Y R O U T I N E S ;--------------------------------------------------------------------------- COUT7: AND 7FH ; Mask off MSB of print COUT: JP BOUT ; Use BOUT for all COUT references ;..... ; Skip over "White Space" delimiter chars in string addressed by HL. ; Return Zero if End-Of-Line. SKWSP: CALL @SDELM ; Use New Z3LIB routine RET NZ OR A RET Z ; Return Zero Set if EOL INC HL ; Not EOL, so advance JR SKWSP ; ..and loop ;..... ; Read a Hex input file to the memory area addressed by HL RDHEX: CALL GETBIN ; Get a raw byte CP ':' ; Start of record? JR NZ,RDHEX ; ..loop til we have it LD D,0 ; Initialize the Checksum reg CALL GETBYT ; Then get the count byte LD B,A ; Else store in reg ADD A,D ; Update cksum LD D,A CALL GETBYT ; .High Address LD H,A ADD A,D ; Update cksum LD D,A CALL GETBYT ; ..Low Address LD L,A ADD A,D LD D,A ; Check for End-of-file Record LD A,B ; Are Count.. OR H ; .Hi Addr OR L ; ..and Lo Addr all Zero? RET Z ; Return if End ; Do some checks for Illegal Addresses LD A,H ; Is this write to Page 0? OR A JR NZ,RDHEX0 ; ..continue if Not (ok) CALL RING ; Ring bell if possible CALL QPRINT ; Else Print an Error message DEFB ' +++ Write to Page 0 +++',0 RET ; ..and return RDHEX0: DEC H ; Since the base starts at 100H, compensate PUSH DE ; Save the Checksum LD DE,(BASADR) ; Get Base of Buffer area ADD HL,DE ; ..and add this record's address PUSH HL ; Save the real load addr LD E,B ; .move the count down LD D,0 ADD HL,DE ; ..and calculate the end CALL CKOVFL ; Will we go too far? (abort if so) POP HL ; Restore Load pointer POP DE ; ..and Checksum CALL GETBYT ; Skip over Type byte ADD A,D LD D,A RDHEX1: CALL GETBYT ; Get a data byte LD (HL),A ; .store INC HL ; ..bump pointer ADD A,D ; Add this byte to Checksum LD D,A ; ..and save DJNZ RDHEX1 ; Count down, loop til done CALL GETBYT ; Get the checksum byte ADD A,D ; Same? JP NZ,CKSERR ; ..jump to Checksum Error if Bad LD DE,(WRKPTR) ; Get the current working Top of buffer CALL COMPHD ; Have we exceeded the old top of used mem? JR C,RDHEX ; .loop if not LD (WRKPTR),HL ; ..else save new top LD DE,(TOPFIL) ; Get old top of Used Memory CALL COMPHD ; Have we expanded the Image size? JR C,RDHEX ; .loop if not LD (TOPFIL),HL ; ..else save new Top JP RDHEX ; ...then loop ;..... ; Convert Hex char in A to binary digit in range 0..15 HEX2BIN: SUB '0' ; Subtract numeric bias CP 10 ; In range 0..9? RET C ; ..return if so SUB 7 ; Subtract difference between 9 and A RET ; ..and quit ;..... ; Search for the file addressed by ZCPR3 style FCB in DE SRCHF: LD DE,FCB ; Use Input FCB if entered here SRCHF0: CALL Z3LOG ; Log into DU for file JP F$EXIST ;..... ; Read a sector of the file to the current DMA address RDSEC: LD DE,FCB ; Point to the Input FCB JP F$READ ; ..and read a sector ;..... ; Open the file at the Input FCB OPENIN: LD DE,FCB ; Point to the Input FCB OPENF: CALL F$OPEN ; ..and Open it LD HL,BUFF+128 ; Set ptr to force read in GETBIN LD (INPTR),HL RET ;..... ; Close the file at the input FCB and restore the current DU: CLOSIN: LD DE,FCB ; Point to the Input FCB CLOSF: CALL F$CLOSE ; ..and Close it RESTOR: LD HL,BUFF ; Get default DMA buffer CALL SETDMA ; ..and Set Transfer Addr LD BC,(CUSER) ; Get current DU: JP LOGUD ; ..log it and return ;..... ; Print Null-Length Error message and exit NULFIL: CALL RING CALL EPRINT DEFB ' +++ Nothing to Save +++',0 JP EXIT ;..... ; Print Overlaying message followed by File ID OVLMSG: CALL QPRINT ; Announce this file DEFB ' Overlaying --> ',0 JR PRNAME ; ..then print file name ;..... ; Print File name with Drive and User from Z3 FCB addressed by DE LODMSG: CALL QPRINT ; Announce this file DEFB ' Loading --> ',0 PRNAME: LD A,(QUIET) ; Print permitted? OR A RET Z ; ..exit here if Not PRNAM1: LD A,(DE) OR A ; Default? JR NZ,PRNAM2 ; ..jump if not LD A,(CUSER+1) ; Else get current INC A PRNAM2: DEC A LD B,A ; Put in the correct reg LD HL,13 ; .offset to User ADD HL,DE LD C,(HL) ; .and get to right reg RES 7,C ; ..clear any MSB CALL DUTDIR ; Check for any named DIR JR Z,PRNAM3 ; ..jump if Not to print DU: PUSH DE ; Save ptr to FCB LD E,8 ; ..and set count PRNAML: LD A,(HL) ; Get a char INC HL ; .bumping ptr CP ' ' ; Is it a space? CALL NZ,COUT ; ..print if not DEC E ; Count down JR NZ,PRNAML ; .loop til done POP DE JR PRNAM4 ; ..then rejoin code PRNAM3: LD A,B ; Print DU: by first getting Drive # ADD A,'A' CALL COUT ; Print Drive Letter LD A,C ; Get User # CALL PAFDC ; ..and Print PRNAM4: LD A,':' CALL COUT INC DE CALL PFN2 ; Print File Name & Type DEC DE JP CRLF ; .go to new line ;..... ; Print File Not Found Error and Exit NFERR: CALL RING CALL QPRINT ; Print Not Found error and abort DEFB ' -- Can''t find : ',0 JR PRNAME ; Print name, Drive, User and return ;..... ; Check for overflow of Address in HL (HL > TOPADR) aborting if so CKOVFL: PUSH DE ; Preserve regs LD DE,(TOPADR) ; Get the base of protected memory CALL COMPHD ; Is DE still greater than HL? POP DE ; .(restore regs) RET C ; ..return if so CALL RING CALL QPRINT ; Else print an error DEFB ' +++ Memory Overflow at : ',0 CALL QPRHEX JR ERREX0 ; ..and exit ;..... ; Print Checksum Error message and Exit CKSERR: CALL RING CALL QPRINT DEFB CR,LF,' +++ Checksum Error +++',0 ERREX0: JP EXIT ; ..abort ;..... ; File Open Error on file described by FCB in DE OPNERR: CALL RING CALL QPRINT DEFB CR,LF,' Can''t Open : ',0 ERREX: CALL PRNAME ; Print Name, Drive & User JR ERREX0 ; ..and take error exit ;..... ; File Read Error on file described by FCB in DE RDERR: CALL RING CALL QPRINT DEFB CR,LF,' Error or EOF Reading : ',0 LD DE,FCB JR ERREX ;..... ; File creation error on completion MAKERR: CALL RING CALL QPRINT DEFB CR,LF,' No Directory Space for : ',0 JR ERREX ;..... ; Get a byte (2 ascii Hex chars) from the Input file. ; Jump to Read Error and Exit if Read Error or Read Past EOF ; Uses: A,C GETBYT: CALL GETBIN ; Get a Hex char CP ' ' ; Is it a Control char (ff,cr,lf..)? JR C,GETBYT ; ..loop back for another if so CALL HEX2BIN ; Convert Hex to Binary RLCA ; Rotate RLCA ; .to RLCA ; ..High RLCA ; ...Nybble LD C,A ; Preserve CALL GETBIN ; Get next Hex digit CALL HEX2BIN ; Convert to Binary ADD A,C ; .and add Hi Nybble RET ;..... ; Return the next available byte from Sector Buffer in the A register. ; Carry Flag is Set if attempt to read past End-of-File or Read Error. GETBIN: PUSH HL ; Preserve all regs LD HL,(INPTR) ; Check the pointer for disk read LD A,H ; Has it overflowed? OR A JR Z,GETBI0 ; ..jump if not to get the byte PUSH DE ; Save rest of the regs PUSH BC CALL RDSEC ; Else Read the disk and reset pointer POP BC ; Restore regs POP DE JR NZ,RDERR ; .jump if Error LD HL,BUFF ; ..else reset the pointer GETBI0: LD A,(HL) ; Get the next byte INC HL ; .bump pointer LD (INPTR),HL ; ..save POP HL ; Restore all regs RET ;..... ; Ring the bell if so configured RING: LD A,(USEBEL) ; Get the flag OR A ; Ring? RET Z ; ..return if Not LD A,BELL ; Else set up the char JP COUT ; ..and do it! ;..... ; Print message only if the ZCPR3 Quiet (or Verbose) Flags permit QPRINT: LD A,(QUIET) ; Get the local quiet flag OR A ; Print permitted? JP NZ,EPRINT ; ..jump to do it if so EX (SP),HL ; Else get the string addr XOR A ; .scan for this char QPLOOP: CP (HL) INC HL ; ..bumping ptr JR NZ,QPLOOP ; ...til found EX (SP),HL ; Then restore regs & stack RET ; ..and return ;..... ; Print the value in HL as 4 Hex chars if the Quiet flag permits QPRHEX: LD A,(QUIET) ; Are we quiet? OR A RET Z ; ..exit here if so JP PHL4HC ; Else go print it ;--------------------------------------------------------------------------- ; S T R I N G S A N D C O N S T A N T S ;--------------------------------------------------------------------------- COMTYP: DEFB 'COM' HEXTYP: DEFB 'HEX' ;--------------------------------------------------------------------------- ; U N I N I T I A L I Z E D D A T A A R E A ;--------------------------------------------------------------------------- DSEG ; Uninitialized Data goes here OFCB: DEFS 36 ; Output File Control Block QUIET: DEFS 1 ; Flag to operate in Quiet Mode INPTR: DEFS 2 ; Pointer into input file buffer CUSER: DEFS 2 ; Current User and Drive TUSER: DEFS 2 ; Temporary User and Drive for File IO SCNPTR: DEFS 2 ; Scan pointer into Command Tail ; Pointers relating to the Buffer Image and Area BASADR: DEFS 2 ; Base of available RAM for work space TOPADR: DEFS 2 ; Top of available RAM protecting CPR TOPFIL: DEFS 2 ; Top address of Output File WRKPTR: DEFS 2 ; Working pointer DEFS 64 ; Space for a stack STACK: DEFS 2 ; Storage for entry stack pointer END