;********************************************************************** ;********************************************************************** ;********************************************************************** ;********************************************************************** ;********************************************************************** ; ; ; ; SSP ; ; ; version 2.0 ; ; ; Copyright 1983 OCCO inc. ; ; ; ; ;********************************************************************** ;********************************************************************** ;********************************************************************** ;********************************************************************** ;********************************************************************** ; ; ; ; SSP CONSTANTS ; OS: EQU 00005H ;OS ENTRY ADDRESS SYSRET: EQU 00000H ;SYSTEM RETURN ADDRESS BUFF1: EQU 02000H ;1ST DATA BUFFER ADDRESS BUFF2: EQU 04000H ;2ND DATA BUFFER ADDRESS SAVDAT: EQU 02100H ;USER SAVE AREA CMDLIN: EQU 0007FH ;COMMAND LINE ADDRESS CMDCNT: EQU 21 ;COMMAND COUNT CR: EQU 0DH ;CARRAGE RETURN LF: EQU 0AH ;LINE FEED TAB: EQU 09H ;TAB SPACE: EQU 20H ;SPACE FRMFED: EQU 0CH ;FORM FEED CHAR EOF: EQU 1AH ;END OF FILE PRNTON: EQU 2 ;PRINTER ON STATUS TO OS CONON: EQU 1 ;CONSOLE ON STATUS TO OS ; ; STATUS BIT DEFINITION ; FILE1: EQU 1 ;BIT1 = 1 =1 FILE IN COMMAND LINE FILE2: EQU 2 ;BIT2 = 1 =2 FILES IN LINE INTACT: EQU 7 ;BIT7 = 0 =INTERACTIVE MODE ; ;********************************************************************** ; ; SSP exec: initialize CPU registers ; set control-C address ; if there are no command line parameters ; then write SSP prompt ; get command line from console ; check for name in command line ; format command name ; if command is disk designator ; then set current disk ; and go back for new command line ; find file names and format into FCB's ; locate command name in command array ; set disk buffer address ; get command routine's address ; set return address ; vector to command routine ; ; on return from command routine: ; if printer output is enabled ; then write 2 form feeds to printer ; turn off printer output and turn on console ; write command routine's return message ; if no command line was present at initialization ; then go back for new command line ; if a command line was present ; then mark flag as if command line was not present ; (to allow for restart from MRS) ; return to MRS ; ;********************************************************************** ; ; ; ORG 100H ; ; SSP: LD SP,(OS+1) ;INIT STACK POINTER LD IX,SYSTAT ;STATUS ARRAY POINTER ; LD DE,CNTRLC ;SET CONTROL-C ABORT LD C,130 ;TO SSP ROUTINE CALL OS ; LD A,(CMDLIN+1) ;GET REMAINING CMD LNGTH OR A,A ;ANY CMD LINE? JR NZ,SSPB ;YES ; SSPA: LD (IX+0),0 ;INIT FLAGS ; LD C,25 ;GET CURRENT DISK# CALL OS ADD A,41H ;CONVERT TO ASCII LD (PRMPT+6),A ;& INIT PROMPT ; LD DE,PRMPT ;WRITE OUT PROMPT LD C,9 CALL OS ; LD DE,CMDLIN ;READ COMMAND LINE FROM CONSOLE LD C,10 CALL OS ; LD A,(CMDLIN+1) ;CMD LINE LENGTH OR A,A ;ANY CMD? JR Z,SSPA ;NO-TRY AGAIN ; LD E,LF ;ECHO LINE FEED LD C,2 CALL OS ; SSPB: LD HL,CMDLIN+2 ;ADDR OF 1ST CHAR CALL FNDNAM ;FIND FILE NAME LD DE,MSG0 ;ERROR MESSAGE JP Z,SSPG ;ERROR IF NO COMMAND NAME ; LD DE,CMDFCB ;CMD WORD FCB LD C,134 CALL OS ;FORMAT CMD WORD ; LD A,(CMDFCB+1) ;GET 1ST CMD NAME CHARACTER CP A,20H ;DISK SPEC ONLY? JR NZ,SSPC ;NO-CONTINUE ; LD A,(CMDFCB) ;YES-GET SPEC SUB A,41H ;CONVERT TO MRS SPEC LD E,A ;SETUP REGISTERS LD C,14 CALL OS ;MAKE NEW CURRENT DRIVE JR SSPA ;DONE-GET NEXT CMD LINE ; SSPC: CALL FNDNAM ;FIND NEXT FILE NAME JR Z,SSPD ;DONE IF NO NAME ; SET 1,(IX+0) ;SET FLAG FOR 1 FILE PARAMETER LD DE,FCB1 ;FORMAT FILE NAME LD C,134 CALL OS ; CALL FNDNAM ;FIND NEXT FILE NAME JR Z,SSPD ;DONE IF NO NAME ; SET 2,(IX+0) ;SET FLAG FOR 2 FILE PARAMETERS RES 1,(IX+0) ;RESET 1 FILE FLAG LD DE,FCB2 ;FORMAT 2ND FILE NAME LD C,134 CALL OS ; SSPD: LD (IX+1),CMDCNT ;SET SEARCH LOOP COUNTER LD HL,CMDTAB ;& POINTERS LD BC,14 ;TABLE ENTRY LENGTH LD DE,CMDFCB ;ACTUAL CMD WORD SSPE: CALL NAMTST ;CMPR WITH TABLE ENTRY JR Z,SSPF ;NAMES MATCH ADD HL,BC ;NO MATCH-BUMP TABLE POINTER DEC (IX+1) ;DECR LOOP COUNT JR NZ,SSPE ;CONTINUE TABLE SCAN LD DE,MSG0 ;ILLEGAL CMD-SEND MESSAGE JR SSPG ; SSPF: LD DE,BUFF1 ;SET DISK BUFFER ADDRESS LD C,26 CALL OS ; LD C,25 ;GET CURRENT DISK# CALL OS LD (CURDSK),A ;& SAVE IT ; PUSH HL ;IY=HL POP IY LD L,(IY+12) ;HL=CMD PROC ADDRESS LD H,(IY+13) LD DE,SSPG ;RETURN ADDRESS PUSH DE JP (HL) ;GO TO CMD PROC ; ; SSPG: PUSH DE ;SAVE MESSAGE ADDRESS LD IX,SYSTAT ;INIT STATUS ARRAY POINTER ; LD C,140 ;GET I/O STATUS CALL OS LD C,2 ;INIT FOR FORMFEED LD E,FRMFED ;TO PRINTER AND A,PRNTON ;PRINTER ENABLED? CALL NZ,OS ;YES-WRITE FORMFEED TO CALL NZ,OS ;PRINTER TWICE ; LD C,142 ;NOW TURN OFF PRINTER LD E,CONON ;& TURN ON CONSOLE CALL OS ; LD DE,(CURDSK) ;GET CURRENT DISK# LD C,14 ;& SET SYSTEM CALL OS ;TO THAT DISK ; POP DE ;RESTORE MESSAGE ADDRESS LD C,9 ;WRITE RETURN MESSAGE CALL OS ; BIT 7,(IX+0) ;SPP CALLED WITH CMD LINE? JP Z,SSPA ;NO-INTERACTIVE MODE ; RES 7,(IX+0) ;SET INTERACTIVE MODE FOR REENTRY LD C,0 ;RETURN TO MRS CALL OS ; ;********************************************************************** ; ; control-C routine: initialize status array pointer ; vector to command return point ; ;********************************************************************** ; ; CNTRLC: LD IX,SYSTAT ;REINIT SYSTEM ARRAY POINTER LD DE,MSG9 ;^C MESSAGE JR SSPG ;CURRENT ROUTINE BYPASSED ;********************************************************************** ; ; compare formatted file names in (DE) & (HL) ; ;********************************************************************** ; ; NAMTST: PUSH HL ;SAVE REGISTERS PUSH DE PUSH BC LD B,11 ;11 CHAR'S IN NAME ; NAMTS2: INC HL ;BUMP POINTERS INC DE LD C,(HL) ;GET 1ST CHARACTER RES 7,C ;STRIP MSB LD A,(DE) ;GET 2ND CHARACTER AND A,7FH ;STRIP MSB CP A,'?' ;UNIVERSAL CHARACTER? JR Z,NAMTS3 ;YES CP A,C ;NO-COMPARE CHARACTERS JR NZ,NAMTS4 ;MISMATCH-DONE NAMTS3: DJNZ NAMTS2 ;CONTINUE SCAN ; NAMTS4: POP BC ;RESTORE REGISTERS POP DE POP HL RET ; ;********************************************************************** ; ; write characters to output through MRS ; ;********************************************************************** ; ; CHROUT: PUSH DE ;SAVE REGISTERS PUSH BC ; LD E,A ;SET UP PARAMETER REGISTER RES 7,E ;STRIP MSB LD C,2 ;CONSOLE CALL CODE CALL OS ;WRITE CHARACTER ; POP BC ;RESTORE REGISTERS POP DE RET ;********************************************************************** ; ; find the first character that is the start of a valid file name ; ;********************************************************************** ; ; FNDNAM: LD A,(HL) ;GET CHAR CALL CHRTST ;TEST CHAR RET NZ ;DONE IF NOT SEPARATOR OR A,A ;TEST FOR END OF LINE RET Z ;DONE IF END OF LINE INC HL ;ELSE BUMP POINTER JR FNDNAM ;& CONTINUE SCAN ; ;********************************************************************** ; ; test for a separator character & return with Z flag set if separator ; ;********************************************************************** ; ; CHRTST: CP A,'.' ;PERIOD? RET Z ;Z=SEPARATOR CHAR CP A,',' ;COMMA? RET Z CP A,'=' ;EQUALS? RET Z CP A,'/' ;SLASH? RET Z CP A,':' ;COLON? RET Z CP A,';' ;SEMICOLON? RET Z CP A,' ' ;SPACE? RET NC ;NZ=ALPHA CHAR BIT 7,A ;Z=SEPARATOR CHAR RET ;********************************************************************** ; ; help: set menu as return message parameter ; and return to SSP exec ; ;********************************************************************** ; ; HELP: LD DE,MSGH ;HELP MESSAGE RET ;WRITE MESSAGE ; ;********************************************************************** ; ; erase: check for single file name in command line ; erase file using MRS call ; return with message indicating # of entries erased ; ;********************************************************************** ; ; ERA: LD DE,MSG1 ;ERROR MESSAGE BIT 1,(IX+0) ;1 FILE SPECIFIED? RET Z ;NO-ERROR ; LD DE,FCB1 ;FCB FOR SPECIFIED FILE LD C,19 ;DELETE CODE CALL OS ;DELETE FILES ; LD (MSG2+1),A ;MSG GETS # OF ENTRIES LD DE,MSG2 ;ERASE MESSAGE RET ;********************************************************************** ; ; rename: check for 2 file names in command line ; move 1st file name into 2nd FCB for MRS rename function ; rename file using MRS call ; return with message indicating # of entries renamed ; ;********************************************************************** ; ; REN: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET Z ;ERROR IF NOT 2 ; LD HL,FCB1 ;PUT FILE NAME1 LD DE,FCB2+16 ;INTO FCB2 LD BC,12 LDIR ; LD DE,FCB2 ;FCB FOR FILE NAMES LD C,23 ;RENAME CODE CALL OS ;RENAME FILES ; LD (MSG3+1),A ;MSG GETS # OF ENTRIES RENAMED LD DE,MSG3 ;RENAME MESSAGE RET ; ;********************************************************************** ; ; print: turn on printer output & turn off console output ; jump to TYPE command routine ; ;********************************************************************** ; ; PRINT: LD C,142 ;SET I/O STATUS LD E,PRNTON ;FOR PRINTER CALL OS JP TYPE ;NOW USE TYPE ROUTINE ;********************************************************************** ; ; print dump: enable printer output & disable console output ; jump to DUMP command routine ; ;********************************************************************** ; ; PDUMP: LD C,142 ;SET I/O STATUS LD E,PRNTON ;FOR PRINTER OUTPUT CALL OS JP DUMP ;NOW USE DUMP ROUTINE ; ;********************************************************************** ; ; type: check for single file name in command line ; open file & check that file exists ; output file contents through MRS ; until file ends (read function parameter <> 0) ; or ; an end-of-file character (EOF) is encountered ; ;********************************************************************** ; ; TYPE: LD DE,MSG1 ;ERROR MESSAGE BIT 1,(IX+0) ;1 FILE SPECIFIED? RET Z ;NO-ERROR ; LD DE,FCB1 ;OPEN FILE LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-OPEN ERROR ; TYPE1: LD DE,FCB1 ;READ SECTOR FROM FILE LD C,20 CALL OS LD DE,MSGD ;ENDING MESSAGE OR A,A ;READ SUCCESSFUL? RET NZ ;DONE IF NO DATA READ ; LD HL,BUFF1 ;INIT PRINT POINTER LD B,128 ;& LOOP COUNT TYPE2: LD A,(HL) ;GET CHAR CP A,EOF ;END OF FILE CHARACTER? RET Z ;YES-DONE CALL CHROUT ;WRITE IT OUT INC HL ;BUMP POINTER DJNZ TYPE2 ;CONTINUE LOOP JR TYPE1 ;NEXT SECTOR ; ;********************************************************************** ; ; dump: check for 2 file names in command line ; open 1st file & check that it exists ; translate 2nd file name into hex number (start address) ; read in file record & dump in hex through MRS output ; until read operation is unsuccessful ; ;********************************************************************** ; ; DUMP: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET Z ;ERROR IF NOT ; LD DE,FCB1 ;OPEN 1ST FILE LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR ; LD IY,FCB2 ;START OF HEX ADDR CALL HEXIN ;GET HEX ADDRESS (INTO 'HL') ; DUMP1: LD DE,FCB1 ;READ IN SECTOR LD C,20 CALL OS ; LD DE,MSGD ;ENDING MESSAGE OR A,A ;READ COMPLETED? RET NZ ;DONE IF NO DATA READ ; LD DE,BUFF1 ;WRITE DATA BLOCK CALL WRBLK ; JR DUMP1 ;CONTINUE WRITE LOOP ; ;********************************************************************** ; ; translate character string into hexadecimal number until a non-hex ; character is encountered. Return with the number in register HL. ; ;********************************************************************** ; HEXIN: LD HL,0 ;INIT # ; HEXIN1: INC IY ;BUMP POINTER TO NEXT CHAR LD A,(IY+0) ;GET CHAR ; CP A,30H ;BELOW # CHAR? RET C ;YES-DONE ; CP A,3AH ;#? JR C,HEXIN2 ;YES-SKIP TO CONVERT ; CP A,41H ;BETWEEN # & ALPHA? RET C ;YES-DONE ; CP A,47H ;LEGAL ALPHA? RET NC ;NO-DONE ; SUB A,7 ;LEGAL ALPHA-ADJUST LSB'S ; HEXIN2: AND A,0FH ;STRIP ASCII BITS ADD HL,HL ;NEW=OLD*16+DIGIT ADD HL,HL ADD HL,HL ADD HL,HL ; OR A,L ;ADD IN NEW DIGIT LD L,A JR HEXIN1 ;CONTINUE TRANSLATE LOOP ; ;********************************************************************** ; ; translate character string into decimal number until non-numerical ; character is encountered. Return with number in register HL. ; ;********************************************************************** ; ; DECIN: LD HL,0 ;INIT# ; DECIN1: INC IY ;BUMP POINTER LD A,(IY+0) ;GET CHAR ; CP A,30H ;BELOW #? RET C ;YES-DONE ; CP A,3AH ;ABOVE #? RET NC ;YES-DONE ; AND A,0FH ;STRIP ASCII BITS PUSH DE ;SAVE REGISTER ; ADD HL,HL ;NEW NUMBER = (8 * OLD NUMBER) PUSH HL POP DE ADD HL,HL ADD HL,HL ADD HL,DE ; + (2 * OLD NUMBER) LD E,A LD D,0 ADD HL,DE ; + NEW DIGIT ; POP DE ;RESTORE REGISTER JR DECIN1 ;CONTINUE TRANSLATE LOOP ; ;********************************************************************** ; ; translate byte in register A into two hex characters and ; output through MRS. Register A is not saved. ; ;********************************************************************** ; ; HEXOUT: PUSH AF ;SAVE CHAR ; SRL A ;ALIGN MSB'S SRL A SRL A SRL A ; CALL HEXOT2 ;WRITE OUT MSB'S ; POP AF ;RESTORE CHAR ; HEXOT2: AND A,0FH ;KEEP LSB'S OR A,30H ;ADD ASCII CP A,3AH ;NUMERIC RANGE? JP C,CHROUT ;YES WRITE OUT ADD A,7 ;NO-ADJUST RANGE JP CHROUT ;THEN WRITE OUT ; ;********************************************************************** ; ; save: check for 2 files specified in command line ; translate 2nd file name into number (# of Kbytes to save) ; initialize return message & check for >0 save value ; create save file & check for room in disk directory ; write data to file ; until disk full ; or ; # of bytes specified is saved ; if disk is full return error message ; if save completed close file & return save message ; ;********************************************************************** ; ; SAVE: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET Z ;NO-ERROR ; LD IY,FCB2 ;GET DECIMAL# INPUT CALL DECIN ; LD (MSG6+1),HL ;INIT MESSAGE ; ADD HL,HL ;SECTOR COUNT=8*KBYTE COUNT ADD HL,HL ADD HL,HL LD (CNTR2),HL ;INIT SECTOR COUNT ; LD DE,MSG6 ;SAVE MESSAGE LD A,L ;TEST FOR INPUT=0 OR A,H RET Z ;ZERO-DONE ; LD HL,SAVDAT ;INIT DATA POINTER LD (CNTR1),HL ; LD DE,FCB1 ;CREATE NEW FILE LD C,22 CALL OS LD DE,MSG7 ;ERROR MESSAGE AND A,80H ;FILE CREATED? RET NZ ;NO-DIRECTORY FULL ; SAVE1: LD DE,(CNTR1) ;GET DATA POINTER LD HL,128 ;AND BUMP TO NEXT FIELD ADD HL,DE LD (CNTR1),HL ;SAVE NEW VALUE FOR NEXT LOOP ; LD C,26 ;SET BUFFER ADDRESS CALL OS ; LD DE,FCB1 ;WRITE SECTOR LD C,21 CALL OS LD DE,MSG8 ;ERROR MESSAGE OR A,A ;SECTOR WRITTEN? RET NZ ;NO-DISK FULL ; LD HL,(CNTR2) ;GET COUNT DEC HL LD (CNTR2),HL LD A,L ;TEST FOR COUNT=0 OR A,H JR NZ,SAVE1 ;CONTINUE TILL COUNT=0 ; LD DE,FCB1 ;CLOSE FILE LD C,16 CALL OS ; LD DE,MSG6 ;SAVE MESSAGE RET ; ;********************************************************************** ; ; transfer: check for 2 file names in command line ; check for destination file name=source file name ; and that disk#'s (for same file names) are different ; create 1st file on disk (destination file) ; if disk directory full then return error message ; transfeer file2 to file1 at 8Kbytes/transfer ; until file2 is exhausted ; or ; disk is full ; if disk is full then return error message ; if transfer completed ; then close file1 ; write transfer message ; jump to CMPR command routine ; ;********************************************************************** ; ; XFER: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET Z ;NO-ERROR ; LD A,(FCB1+1) ;GET 1ST CHAR OF FILE NAME CP A,20H ;FILE NAME SPECIFIED? JR NZ,XFER1 ;YES LD HL,FCB2+1 ;NO-USE 2ND FILE NAME LD DE,FCB1+1 LD BC,11 LDIR LD A,(FCB1+9) ;REMOVE PROTECT BIT AND A,7FH ;FROM FILE NAME LD (FCB1+9),A ; LD HL,FCB1 ;COMPARE FCB DISK#'S LD A,(FCB2) LD DE,MSG37 ;ERROR MESSAGE CP A,(HL) ;#1=#2? RET Z ;YES-ERROR ; XFER1: LD DE,FCB2 ;OPEN FILE2 LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR ; LD DE,FCB1 ;CREATE FILE1 LD C,22 CALL OS LD DE,MSG7 ;ERROR MESSAGE AND A,80H ;DIRECTORY FULL? RET NZ ;YES-DONE ; XFER2: LD HL,FCB2 ;READ FILE2 LD DE,BUFF1 ;INTO BUFFER1 CALL RDBUF ; LD HL,FCB1 ;WRITE INTO FILE1 LD DE,BUFF1 ;FROM BUFFER1 CALL WRBUF ; LD DE,MSG8 ;ERROR MESSAGE RET NZ ;DONE-DISK FULL ; LD A,(IX+2) ;GET SECTOR COUNT OR A,A ;ANYTHING READ? JR NZ,XFER2 ;YES-CONTINUE XFER LOOP ; LD DE,FCB1 ;CLOSE FILE1 LD C,16 CALL OS ; LD DE,MSG10 ;WRITE XFER MESSAGE LD C,9 CALL OS ; JP CMPR ;NOW COMPARE FILES ; ;********************************************************************** ; ; compare: check for 2 file names in command line ; check for 1st file name to be same as 2nd file name ; open files & check that they exist ; read files into data buffers ; check for same data size in each buffer ; if not same length then return error message ; keep track of total file size ; compare files & keep track of number of errors ; continue last 5 steps until all file records are read ; return with message indicating the total file ; size in records and the number of errors encountered ; ;********************************************************************** ; ; CMPR: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET Z ;NO-ERROR ; LD A,(FCB1+1) ;GET 1ST CHAR OF FILE NAME CP A,20H ;1ST FILE NAME SPECIFIED? JR NZ,CMPR1 ;YES LD HL,FCB2+1 ;NO-USED 2ND FILE NAME LD DE,FCB1+1 LD BC,11 LDIR ; CMPR1: LD DE,FCB1 ;OPEN FIRST FILE LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR ; LD DE,FCB2 ;OPEN FILE2 LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR ; LD IY,0 ;INIT RECORD COUNT LD (MSG12+27),IY ;INIT ERROR COUNT ; CMPR2: LD HL,FCB1 ;READ FILE1 LD DE,BUFF1 ;INTO BUFFER1 CALL RDBUF PUSH AF ;SAVE FILE1 SECTOR COUNT ; LD HL,FCB2 ;READ FILE2 LD DE,BUFF2 ;INTO BUFFER2 CALL RDBUF ; LD DE,MSG11 ;ERROR MESSAGE POP AF ;RESTORE FILE1 SECTOR COUNT CP A,(IX+2) ;SAME AS FILE1? RET NZ ;NO-LENGTH ERROR OR A,A ;ANYTHING READ? JR Z,CMPRE ;NO-DONE ; LD C,A ;SETUP ADDITION LD B,0 ADD IY,BC ;BUMP RECORD COUNT LD B,128 ;INITIAL LOOP COUNT LD HL,BUFF1 ;SETUP POINTERS LD DE,BUFF2 ;FOR COMPARE LOOP ; CMPR4: LD A,(DE) ;GET 1ST CHAR CP A,(HL) ;CMPR TO 1ST BUFFER JR Z,CMPR6 ;SKIP IF NO MISMATCH PUSH HL ;SAVE REGISTER LD HL,(MSG12+27) ;BUMP ERROR COUNT INC HL LD (MSG12+27),HL POP HL ;RESTORE REGISTER ; CMPR6: INC DE ;BUMP POINTERS INC HL DJNZ CMPR4 ;CONTINUE CMPR LOOP ; LD B,128 ;INIT FOR NEXT CMPR LOOP DEC C ;DECR SECTOR COUNT JR NZ,CMPR4 ;CONTINUE LOOP JR CMPR2 ;GO BACK AND REFILL BUFFERS ; CMPRE: LD (MSG12+1),IY ;STORE RECORD COUNT IN MESSAGE LD DE,MSG12 ;COMPARE MESSAGE RET ; ;********************************************************************** ; ; merge: check for 2 file names in command line ; open files & check that they exist ; find last sector in file1 ; read the last sector ; find 1st EOF in last sector ; read in file2 data over EOF's in file1 data ; write out data to file1 ; move remaining data to top of buffer ; read in more file2 data after remaining data in buffer ; write data to file1 ; continue last 3 steps until file2 exhausted ; close file1 ; ;********************************************************************** ; ; MERGE: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET Z ;NO-ERROR ; LD DE,FCB1 ;OPEN FILE1 LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR ; LD DE,FCB2 ;OPEN FILE2 LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR ; LD C,35 ;FIND NEXT RCD# IN FILE LD DE,FCB1 CALL OS LD HL,(FCB1+33) ;SET RCD# TO LAST RECORD DEC HL LD (FCB1+33),HL ; LD C,33 ;READ LAST RECORD LD DE,FCB1 CALL OS ; LD HL,BUFF1 ;FIND 1ST OCCURENCE LD BC,129 ;OF ASCII END OF FILE LD A,EOF CPIR DEC HL ;POINT TO LAST CHAR LD (CNTR3),HL ;SAVE READ ADDRESS ; MERG6: LD HL,FCB2 ;READ FROM FILE2 LD DE,(CNTR3) CALL RDBUF LD HL,FCB1 ;WRITE TO FILE1 LD DE,BUFF1 CALL WRBUF LD D,(IX+2) ;COMPUTE ADDRESS OF LD E,0 ;LAST BYTE+1 SRL D RR E LD HL,BUFF1 ADD HL,DE ;HL=ADDR OF NEXT BYTE LD DE,BUFF1 ;TRANSFER LAST BYTE LD BC,128 ;TO BEGINNING OF BUFFER LDIR BIT 6,(IX+2) ;FULL BUFFER READ? JR NZ,MERG6 ;YES-CONTINUE TRANSFER LD A,(BUFF1) ;GET 1ST CHAR OF LAST RECORD CP A,EOF ;EMPTY RECORD? JR Z,MERG8 ;YES-SKIP WRITING LAST RECORD LD HL,(CNTR3) ;NO-FILL IN LAST SECTOR LD DE,(CNTR3) ;WITH EOF'S INC DE LD BC,128 LD (HL),EOF LDIR LD DE,BUFF1 ;SET BUFFER ADDRESS LD C,26 CALL OS LD DE,FCB1 ;WRITE LAST SECTOR LD C,21 CALL OS ; MERG8: LD DE,FCB1 ;CLOSE FILE1 LD C,16 CALL OS LD DE,MSG13 ;MERGE MESSAGE RET ; ;********************************************************************** ; ; initialize: check for 2 file names in command line ; initialize extension of 2nd file name with "BOT" ; (bootstrap file) ; open file & check that it exists ; read in 1st sector of file ; initialize extension again with "SYS" (MRS system file) ; open file and check that it exists ; read in file data after the bootstrap sector ; write the data to the system tracks of the ; specified disk using the BIOS routines ; return with message indicating the number of sectors ; written to the system portion of the disk ; ;********************************************************************** ; ; INIT: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET Z ;NO-ERROR ; LD IY,FCB2 ;INIT FILE EXTENSION LD (IY+9),'B' ;FOR BOOT FILE LD (IY+10),'O' LD (IY+11),'T' ; LD DE,FCB2 ;OPEN FILE LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE OPENED? RET NZ ;NO-DONE ; LD DE,FCB2 ;FILE OPENED-READ DATA LD C,20 CALL OS LD DE,MSG21 ;ERROR MESSAGE OR A,A ;FILE DATA READ? RET NZ ;NO-DONE ; LD (IY+9),'S' ;INIT FILE EXTENSION LD (IY+10),'Y' ;FOR SYSTEM FILE LD (IY+11),'S' ; LD DE,FCB2 ;OPEN FILE2 LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR ; LD HL,FCB2 ;READ IN FILE2 LD DE,BUFF1+128 CALL RDBUF ; INC A ;ADD BOOT SECTOR TO COUNT LD (MSG14+1),A ;GIVE# OF SECTORS TO MESSAGE LD (IX+1),A ;INIT COUNTER ; LD A,(FCB1) ;SAVE DISK# LD (IX+7),A ;IN STATUS ARRAY LD HL,BUFF1 ;INIT BUFFER POINTER LD (BPNTR),HL LD HL,0 ;INIT RECORD COUNTER LD (RCDCNT),HL ; INITA: LD DE,(BPNTR) ;GET BUFFER POINTER LD HL,128 ;POINTER INCR VALUE ADD HL,DE ;GET NEXT LOOP'S VALUE LD (BPNTR),HL ;& SAVE IT LD C,26 ;NOW SET DMA ADDRESS CALL OS ;WITH CURRENT VALUE ; LD DE,(RCDCNT) ;GET RECORD COUNTER INC DE ;GET NEXT LOOP'S VALUE LD (RCDCNT),DE ;& SAVE IT DEC DE ;GET CURRENT VALUE LD B,(IX+7) ;GET DISK# LD C,132 ;& WRITE LOGICAL RECORD CALL OS ; DEC (IX+1) ;DECR LOOP COUNTER JR NZ,INITA ;& CONTINUE ; LD DE,MSG14 ;INIT MESSAGE RET ;WRITTEN ON RETURN ; ;********************************************************************** ; ; copy: check for 2 file names in command line ; write out check message and get answer ; if answer <> "Y" then return ; read in track from disk2 ; write to same track of disk1 ; send track number to console ; continue until all records copied ; ;********************************************************************** ; ; COPY: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 DISKS SPECIFIED? RET Z ;NO-ERROR ; LD A,(FCB1) ;INIT DISK1# LD (IX+7),A OR A,A ;DISK SPECIFIED? RET Z ;NO-RETURN OR A,40H ;ADD ASCII LD (MSG15+29),A ;GIVE TO MESSAGE ; LD A,(FCB2) ;INIT DISK2# LD (IX+8),A OR A,A ;DISK SPECIFIED? RET Z ;NO-RETURN OR A,40H ;ADD ASCII LD (MSG15+19),A ;GIVE TO MESSAGE ; LD DE,MSG15 ;WRITE OUT VERIFY REQUEST LD C,9 CALL OS LD DE,CMDLIN ;GET RESPONSE LD C,10 CALL OS LD E,LF ;ECHO LINE FEED LD C,2 CALL OS LD DE,MSGD ;RETURN MESSAGE LD A,(CMDLIN+2) ;GET RESPONSE CP A,'Y' ;AFFIRMATIVE? RET NZ ;NO-DONE ; LD E,(IX+7) ;GET DESTINATION DISK# DEC E ;& MAKE IT LD C,14 ;THE CURRENT DISK CALL OS LD C,31 ;NOW GET THE DPB ADDRESS CALL OS PUSH HL ;& MOVE IT TO 'IY' POP IY ; LD L,(IY+0) ;INIT THE SECTOR/TRACK COUNT LD H,(IY+1) LD (SECTRK),HL LD L,(IY+5) ;GET THE DSM VALUE LD H,(IY+6) INC HL ;ADJUST FOR ACTUAL VALUE LD B,(IY+2) ;GET THE BSH VALUE COPYB: ADD HL,HL ;USER RECORD COUNT = DJNZ COPYB ;(DSM+1) * (2 ** BSH) LD (TOTRCD),HL ;SAVE USER RECORD COUNT LD C,(IY+13) ;GET TRACK OFFSET LD B,(IY+14) LD DE,(SECTRK) ;GET SECTORS/TRACK LD HL,0 ;INIT COUNT COPYB1: ADD HL,DE ;SYSTEM RECORD COUNT = DEC BC ;SPT * OFF LD A,C OR A,B JR NZ,COPYB1 LD DE,(TOTRCD) ;GET USER RECORD COUNT ADD HL,DE ;TOTAL = USER + SYSTEM LD (TOTRCD),HL LD HL,0 ;INIT THE TRACK COUNT LD (TRKCNT),HL LD (RCDCNT),HL ;& THE RECORD COUNT ; COPYC: LD HL,(TRKCNT) ;GIVE MESAGE THE TRACK COUNT LD (MSG16+8),HL INC HL ;BUMP THE COUNT FOR NEXT LOOP LD (TRKCNT),HL ;& SAVE IT LD DE,MSG16 ;WRITE OUT TRACK COUNT MESSAGE LD C,9 CALL OS ; LD HL,(SECTRK) ;INIT THE SECTOR COUNT LD (SECNT),HL LD HL,BUFF1 ;INIT THE BUFFER POINTER LD (BPNTR),HL ; COPYD: LD DE,(BPNTR) ;GET THE BUFFER POINTER LD HL,128 ;POINTER INCR VALUE ADD HL,DE ;BUMP POINTER FOR NEXT LOOP LD (BPNTR),HL ;& SAVE IT LD C,26 ;NOW SET THE DMA ADDRESS CALL OS ; LD DE,(RCDCNT) ;GET THE RECORD COUNT INC DE ;BUMP FOR THE NEXT LOOP LD (RCDCNT),DE ;& SAVE IT DEC DE ;BACK TO CURRENT VALUE LD B,(IX+8) ;SOURCE DISK# LD C,131 ;& READ FROM THE SOURCE DISK CALL OS ; LD HL,(SECNT) ;GET THE SECTOR COUNT DEC HL ;DECR IT LD (SECNT),HL ;& SAVE IT LD A,L ;CHECK IT OR A,H JR NZ,COPYD ;& CONTINUE READ LOOP ; LD HL,(RCDCNT) ;GET RECORD COUNTER LD DE,(SECTRK) ;GET SPT VALUE LD (SECNT),DE ;INIT SECTOR COUNT OR A,A ;CLEAR CARRY SBC HL,DE ;SET RECORD COUNTER TO LD (RCDCNT),HL ;START OF THE TRACK ; LD HL,BUFF1 ;INIT BUFFER POINTER LD (BPNTR),HL ; COPYE: LD DE,(BPNTR) ;GET BUFFER POINTER LD HL,128 ;POINTER INCR VALUE ADD HL,DE ;BUMP POINTER FOR NEXT LOOP LD (BPNTR),HL ;& SAVE IT LD C,26 ;USE CURRENT VALUE AS DMA ADDRESS CALL OS ; LD DE,(RCDCNT) ;GET RECORD COUNTER INC DE ;BUMP FOR NEXT LOOP LD (RCDCNT),DE ;& SAVE IT DEC DE ;RESTORE CURRENT VALUE LD B,(IX+7) ;DESTINATION DISK# LD C,132 ;& WRITE RECORD TO DISK CALL OS ; LD HL,(TOTRCD) ;DECR THE RECORD COUNT DEC HL LD (TOTRCD),HL ;& SAVE IT LD A,L ;CHECK FOR END OF DESTINATION DISK OR A,H JR Z,COPYF ;EXIT IF DONE ; LD HL,(SECNT) ;GET SECTOR COUNT DEC HL ;DECR IT LD (SECNT),HL ;& SAVE IT LD A,L ;CHECK FOR END OF TRACK OR A,H JR NZ,COPYE ;CONTINUE TRACK WRITE ; JP COPYC ;DO NEXT TRACK ; COPYF: LD C,37 ;RESET THE DISK SYSTEM CALL OS LD DE,MSG19 ;COPY SIGNOFF RET ;WRITTEN ON RETURN ; ;********************************************************************** ; ; patch: check for single file name in command line ; if file name is only disk designator ; then set limit for max records on disk ; if file name exists on disk ; then set limit for max records in file ; write prompt & get command ; if no command then read next logical record ; and go back for next command ; if there is a command then vector to the command routine ; ;********************************************************************** ; ; PATCH: LD DE,MSG1 ;ERROR MESSAGE BIT 1,(IX+0) ;1 FILE SPECIFIED? RET Z ;NO-ERROR ; LD HL,-1 LD (MSG22+8),HL ;INIT RECORD# ; LD IY,FCB1 ;FCB POINTER LD A,(IY+1) ;1ST CHAR OF FILE NAME CP A,20H ;DISK OR FILE? JR NZ,PATCH4 ;FILE ; LD A,(FCB1) ;GET DISK# DEC A ;ADJUST LD E,A ;& SELECT THE DISK LD C,14 CALL OS LD C,31 ;NOW GET THE DPB ADDRESS CALL OS PUSH HL ;MOVE IT TO 'IY' POP IY ; LD L,(IY+5) ;GET THE DSM VALUE LD H,(IY+6) INC HL ;ADJUST FOR ACTUAL VALUE LD B,(IY+2) ;GET THE BSH VALUE PATCH1: ADD HL,HL ;USER RECORD COUNT = DJNZ PATCH1 ;(DSM+1) * (2 ** BSH) LD (TOTRCD),HL ;SAVE USER RECORD COUNT LD C,(IY+13) ;GET TRACK OFFSET LD B,(IY+14) LD E,(IY+0) ;GET SECTORS/TRACK LD D,(IY+1) LD HL,0 ;INIT COUNT PATCH2: ADD HL,DE ;SYSTEM RECORD COUNT = DEC BC ;SPT * OFF LD A,C OR A,B JR NZ,PATCH2 LD DE,(TOTRCD) ;GET USER RECORD COUNT ADD HL,DE ;TOTAL = USER + SYSTEM LD (MSG20+28),HL JP PATCHD ; PATCH4: LD DE,FCB1 ;OPEN FILE LD C,15 CALL OS LD DE,MSG4 AND A,80H ;FILE OPENED? RET NZ ;NO-DONE ; LD DE,FCB1 ;YES-GET MAX RECORD# LD C,35 CALL OS LD HL,(FCB1+33) ;HL=MAX# + 1 DEC HL LD (MSG20+28),HL ;SAVE MAX RECORD# ; PATCHD: LD DE,MSG20 ;WRITE RECORD BOUNDS LD C,9 CALL OS ; PATCHE: LD DE,MSG23 ;WRITE PATCH PROMPT LD C,9 CALL OS ; LD DE,CMDLIN ;GET COMMAND LD C,10 CALL OS LD E,LF ;ECHO LF LD C,2 CALL OS ; LD A,(CMDLIN+1) ;GET COMMAND LENGTH LD HL,(MSG22+8) ;GET NEXT RECORD# INC HL OR A,A ;ANY INPUT? JP Z,PRD2 ;NO-READ NEXT RECORD ; LD A,(CMDLIN+2) ;GET 1ST CMD CHAR CP A,'R' ;READ CMD? JP Z,PRD CP A,'W' ;WRITE CMD? JP Z,PWR CP A,'M' ;MODIFY CMD? JP Z,PMOD CP A,'A' ;ASCII INSERT CMD? JP Z,PASC CP A,'I' ;INIT RECORD CMD? JP Z,PINT CP A,'H' ;HELP REQUEST? JP Z,PHLP CP A,'E' ;END REQUEST? LD DE,MSGD ;END MESSAGE RET Z ;DONE ; LD DE,MSG0 ;ILLEGAL CMD LD C,9 ;SEND MESSAGE CALL OS JR PATCHE ;TRY AGAIN ; PHLP: LD DE,MSGPH ;WRITE HELP MESSAGE LD C,9 CALL OS JP PATCHD ;RETURN TO CMD LOOP ; PRD: LD IY,CMDLIN+2 ;LINE SCAN POINTER CALL DECIN ;GET RECORD# PRD2: PUSH HL ;SAVE RECORD# LD DE,(MSG20+28) ;GET MAX# INC DE OR A,A ;CLEAR CARRY SBC HL,DE ;NEW# : MAX#? POP HL ;RESTORE RECORD# LD DE,MSG24 ;ERROR MESSAGE LD C,9 CALL NC,OS ;NEW# > MAX#-WRITE ERROR JP NC,PATCHD ;& RETURN TO CMD LOOP LD (MSG22+8),HL ;INIT MESSAGE LD (FCB1+33),HL ;SET RECORD# ; LD A,(FCB1+1) ;GET 1ST NAME CHARACTER CP A,20H ;DISK OR FILE? JR Z,PRD3 ;DISK LD DE,FCB1 ;FILE-READ RECORD LD C,33 CALL OS JR PRD4 ;CONTINUE ; PRD3: EX DE,HL ;DE=RCD# LD A,(FCB1) ;GET DISK# LD B,A LD C,131 ;READ CODE CALL OS ;READ DISK RECORD ; PRD4: LD DE,MSG22 ;WRITE RECORD# LD C,9 CALL OS LD HL,0 ;WRITE DATA BLOCK IN HEX LD DE,BUFF1 ;USING ADDRESS=0 CALL WRBLK JP PATCHE ;RETURN TO CMD LOOP ; PWR: LD IY,CMDLIN+2 ;CMD LINE SCANN POINTER CALL DECIN ;GET RECORD# PWR2: PUSH HL ;SAVE # LD DE,(MSG20+28) ;GET MAX# INC DE OR A,A ;CLEAR CARRY SBC HL,DE ;NEW# : MAX#? POP HL ;RESTORE RECORD# LD DE,MSG24 ;ERROR MESSAGE LD C,9 CALL NC,OS ;NEW# > MAX#-ERROR JP NC,PATCHD ;RETURN TO CMD LOOP LD (MSG22+8),HL ;INIT MESSAGE LD (FCB1+33),HL ;SET RECORD# ; LD A,(FCB1+1) ;GET 1ST NAME CHARACTER CP A,20H ;DISK OR FILE? JR Z,PWR3 ;DISK LD DE,FCB1 ;FILE-WRITE RECORD LD C,34 CALL OS JR PWR4 ;CONTINUE ; PWR3: EX DE,HL ;DE=RCD# LD A,(FCB1) ;GET DISK# LD B,A LD C,132 ;WRITE CODE CALL OS ;WRITE DISK RECORD ; PWR4: JP PATCHE ;RETURN TO CMD LOOP ; PINT: LD IY,CMDLIN+2 ;CMD LINE SCAN POINTER CALL HEXIN ;GET INIT VALUE LD A,L LD HL,BUFF1 ;SET WHOLE BUFFER TO VALUE LD DE,BUFF1+1 LD BC,127 LD (HL),A LDIR LD DE,MSG22 ;WRITE OUT RECORD# LD C,9 CALL OS LD HL,0 ;WRITE OUT BLOCK LD DE,BUFF1 CALL WRBLK JP PATCHE ;RETURN TO CMD LOOP ; PMOD: LD IY,CMDLIN+2 ;CMD LINE SCAN POINTER CALL HEXIN ;GET BYTE OFFSET INTO BUFFER LD H,0 ;MAX OFFSET=255 LD DE,BUFF1 ;CALCULATE BYTE ADDRESS ADD HL,DE ;HL=BYTE ADDRESS PMOD2: LD A,(IY+0) ;GET NEXT CMD CHAR OR A,A ;END OF LINE? JR Z,PMOD4 ;YES-DONE PUSH HL ;NO-SAVE POINTER CALL HEXIN ;GET NEXT DATA VALUE LD A,L POP HL ;RESTORE POINTER LD (HL),A ;BYTE=NEW VALUE INC HL ;BUMP POINTER JR PMOD2 ;CONTINUE MODIFY LOOP PMOD4: LD DE,MSG22 ;WRITE RECORD# LD C,9 CALL OS LD HL,0 ;WRITE OUT DATA BLOCK LD DE,BUFF1 CALL WRBLK JP PATCHE ;RETURN TO CMD LOOP ; PASC: LD IY,CMDLIN+2 ;CMD LINE SCAN POINTER CALL HEXIN ;GET BYTE OFFSET LD H,0 ;MAX OFFSET=255 LD DE,BUFF1 ;CALCULATE BYTE ADDRESS ADD HL,DE ;HL=BYTE ADDRESS PASC2: INC IY ;POINTER TO NEXT CHAR LD A,(IY+0) ;TRANSFER LINE TO BUFFER OR A,A ;END OF LINE? JR Z,PASC4 ;YES-DONE LD (HL),A ;NO-BYTE=NEW VALUE INC HL ;BUMP BYTE POINTER JR PASC2 ;CONTINUE MODIFY LOOP PASC4: LD DE,MSG22 ;WRITE RECORD# LD C,9 CALL OS LD HL,0 ;WRITE OUT DATA BLOCK LD DE,BUFF1 CALL WRBLK JP PATCHE ;RETURN TO CMD LOOP ; ;********************************************************************** ; ; print directory: enable printer & disable console output ; jump to "DIR" command routine ; ;********************************************************************** ; ; PDIR: LD C,142 ;SET I/O STATUS LD E,PRNTON ;FOR PRINTER ON CALL OS JP DIR ;NOW USE DIRECTORY FUNCTION ; ; ;********************************************************************** ; ; protect: set the specified file flags to protect files ; ;********************************************************************** ; ; PROTCT: LD DE,MSG1 ;RETURN MESSAGE BIT 1,(IX+0) ;1 FILE SPECIFIED? RET Z ;NO-ERROR LD IY,FCB1 ;INIT FCB POINTER ; LD A,(IY+1) ;GET 1ST CHARACTER OF FILE NAME CP A,SPACE ;ONLY DISK SPECIFIED? JR NZ,PROTCB ;NO-FILE NAME SPECIFIED ; LD E,(IY+0) ;GET DISK SPEC DEC E ;ADJUST RANGE LD C,14 CALL OS ;MAKE DISK CURRENT DISK LD C,28 ;NOW PROTECT DISK CALL OS LD A,(FCB1) ;GET DISK# OR A,40H ;ADD ASCII LD (MSG43+5),A ;ADD TO MESSAGE LD DE,MSG43 ;WRITE MESSAGE RET ;ON RETURN ; PROTCB: SET 7,(IY+9) ;SET PROTECT BIT IN FILE NAME LD DE,FCB1 ;SETUP REGISTERS LD C,30 CALL OS ;PROTECT FILES LD (MSG44+1),A ;GIVE ENTRY COUNT TO MESSAGE LD DE,MSG44 ;& WRITE MESSAGE RET ;ON RETURN ;********************************************************************** ; ; release: reset protect bit of specified file(s) ; ;********************************************************************** ; ; RELEAS: LD DE,MSG1 ;RETURN MESSAGE BIT 1,(IX+0) ;1 FILE SPECIFIED? RET Z ;NO-ERROR ; LD DE,FCB1 ;SETUP REGISTERS LD C,30 CALL OS ;RESET PROTECT BIT LD (MSG45+1),A ;GIVE ENTRY COUNT TO MESSAGE LD DE,MSG45 ;& WRITE MESSAGE RET ;ON RETURN ; ;********************************************************************** ; ; directory: init & read in directory ; loop1 : init & set cluster array ; init entries ; find files (low entry #'s) & save in array ; loop2 : for each file in the file array do: ; find matching entries ; total file size & entry count ; check for allocation errors ; total errors & used blocks from cluster array ; sort files using bubble sort ; print file names & statistics ; compose & print disk statistics ; ;********************************************************************** ; ; DIR: BIT 1,(IX+0) ;ANY FILE SPECIFIED? JR NZ,DIRA ;YES LD A,0 ;NO-SET TO CURRENT DISK LD (FCB1),A LD A,SPACE ;& SET TO GENERAL FILE NAME LD (FCB1+1),A ; DIRA: LD A,(FCB1) ;GET DISK# AND A,0FH ;MAKE <16 JR NZ,DIRA1 ;SKIP IF DISK SPECIFIED LD C,25 ;ELSE GET CURRENT DISK# CALL OS INC A ;SET FOR FCB DISK SPEC DIRA1: LD (FCB1),A ;INIT FCB ; LD A,(FCB1+1) ;GET 1ST CHARACTER IN FILE NAME CP A,SPACE ;FILE NAME SPECIFIED? JR NZ,DIRA2 ;YES LD HL,FCB1+1 ;NO-SET TO GENERAL FILE NAME LD DE,FCB1+2 LD BC,10 LD (HL),'?' LDIR ; DIRA2: LD A,(FCB1) ;GET DISK SPEC DEC A ;ADJUST LD E,A ;NOW USE TO SET CURRENT DISK LD C,14 CALL OS ; DIRA3: LD C,31 ;GET DPB ADDRESS FROM OS CALL OS LD DE,SPT ;XFER TO DPB BUFFER LD BC,15 LDIR ; DIRA4: RES 6,(IX+0) ;RESET CLUSTER SIZE BIT (1 BYTE/CLUSTER) LD A,(DSM+1) ;TEST FOR CLUSTER SIZE OR A,A JR Z,DIRA5 ;1 BYTE/CLUSTER SET 6,(IX+0) ;2 BYTES/CLUSTER ; DIRA5: LD A,(EXM) ;INVERT EXTENT MASK CPL LD (IX+7),A ;& SAVE IT ; LD HL,0 ;INIT USED ENTRIES COUNT LD (UENT),HL LD HL,BUFF2 ;& BUFFER POINTER LD (BPNTR),HL LD DE,FCB1 ;FIND 1ST FILE ENTRY LD C,17 CALL OS JR DIRA7 ; DIRA6: LD C,18 ;FIND NEXT ENTRY CALL OS DIRA7: AND A,80H ;ANY ENTRY FOUND? JR NZ,DIRA8 ;NO BIT 0,(HL) ;YES-ENTRY USED? JR NZ,DIRA6 ;NO-TRY AGAIN LD DE,(BPNTR) ;YES-XFER TO BUFFER LD BC,32 LDIR LD (BPNTR),DE ;SAVE FOR NEXT ENTRY LD HL,(UENT) ;INCR THE USED ENTRY COUNT INC HL LD (UENT),HL JR DIRA6 ;CONTINUE DIRECTORY SEARCH ; DIRA8: LD HL,(UENT) ;GET USED ENTRY COUNT LD DE,MSG41 ;RETURN MESSAGE LD A,L ;ANY ENTRIES FOUND? OR A,H RET Z ;NO-DONE ; DIRB: LD HL,BUFF1 ;CLEAR THE CLUSTER ARRAY LD DE,BUFF1+1 LD BC,0FFFH LD (HL),0 LDIR ; LD IY,BUFF2 ;ENTRY POINTER LD HL,(UENT) ;INIT ENTRY COUNTER LD (ECNTR),HL LD HL,(BPNTR) ;SETUP FILE ARRAY ADDRESS POINTER LD (FPNTR),HL LD HL,0 ;INIT FILE COUNT LD (TOTFIL),HL ; DIRB1: LD A,(IY+12) ;GET EXTENT# LD (IY+12),0 ;INIT ENTRY BYTES LD (IY+13),0 LD (IY+14),0 LD (IY+15),0 ; AND A,(IX+7) ;KEEP MSB'S OF EXTENT# JR NZ,DIRB2 ;NOT 1ST EXTENT PUSH IY ;1ST EXTENT-PUT ADDRESS IN FILE ARRAY POP DE LD HL,(FPNTR) ;ARRAY POINTER LD (HL),E ;STORE ADDRESS INC HL LD (HL),D INC HL LD (FPNTR),HL ;SAVE ARRAY POINTER LD HL,(TOTFIL) ;BUMP FILE COUNT INC HL LD (TOTFIL),HL ; DIRB2: PUSH IY ;GET ADDRESS OF ENTRY'S CLUSTER ARRAY POP HL LD DE,16 ADD HL,DE ;HL=ADDRESS LD B,16 ;16 CLUSTER/ENTRY BIT 6,(IX+0) ;16 OR 8 ? JR Z,DIRB3 ;16 LD B,8 ;8 ; DIRB3: LD E,(HL) ;GET CLUSTER# INC HL LD D,0 BIT 6,(IX+0) ;2 BYTES/CLUSTER? JR Z,DIRB4 ;NO-1 LD D,(HL) ;YES-GET 2ND BYTE INC HL DIRB4: LD A,E ;CHECK FOR CLUSTER=0 OR A,D JR Z,DIRB5 ;SKIP IF CLUSTER#=0 INC (IY+13) ;BUMP CLUSTER COUNT FOR ENTRY PUSH HL ;SAVE NEXT CLUSTER'S ADDRESS LD HL,BUFF1 ;BASE ADDRESS OF CLUSTER ARRAY ADD HL,DE ;USE CLUSTER# AS OFFSET INC (HL) ;BUMP CORRESPONDING ARRAY ENTRY POP HL ;RESTORE CLUSTER ADDRESS DIRB5: DJNZ DIRB3 ;REPEAT FOR ALL CLUSTERS IN ENTRY ; LD DE,32 ;BUMP ENTRY POINTER ADD IY,DE LD HL,(ECNTR) ;DECR ENTRY COUNTER DEC HL LD (ECNTR),HL LD A,L ;CHECK COUNTER OR A,H JR NZ,DIRB1 ;REPEAT FOR ALL ENTRIES ; DIRC: LD HL,(BPNTR) ;INIT FILE ARRAY POINTER LD (FPNTR),HL LD HL,(TOTFIL) ;INIT FILE ARRAY COUNTER LD (FCNTR),HL ; DIRC1: LD IY,(FPNTR) ;GET POINTER LD L,(IY+0) ;GET FILE ADDRESS LD H,(IY+1) PUSH HL ;PUT IN 'IY' POP IY LD HL,0 ;INIT FILE SIZE LD (FSIZE),HL LD HL,BUFF2 ;INIT ENTRY POINTER LD (EPNTR),HL LD HL,(UENT) ;INIT ENTRY COUNTER LD (ECNTR),HL ; DIRC2: PUSH IY ;SETUP REGISTERS POP HL LD DE,(EPNTR) CALL NAMTST ;ENTRY IN FILE? JR NZ,DIRC6 ;NO LD HL,13 ;YES-GET ENTRY'S CLUSTER COUNT ADD HL,DE ;HL=CLUSTER COUNT ADDRESS LD E,(HL) ;DE=COUNT LD D,0 LD HL,(FSIZE) ;ADD TO TOTAL FILE SIZE ADD HL,DE LD (FSIZE),HL INC (IY+12) ;BUMP FILE'S ENTRY COUNT ; LD DE,(EPNTR) ;GET ENTRY ADDRESS LD HL,16 ;COMPUTE CLUSTER ARRAY ADDRESS ADD HL,DE ;IN ENTRY LD B,16 ;16 CLUSTERS/ENTRY BIT 6,(IX+0) ;16 OR 8 ? JR Z,DIRC3 ;16 LD B,8 ;8 ; DIRC3: LD E,(HL) ;GET CLUSTER# LD D,0 INC HL BIT 6,(IX+0) ;1 BYTE/CLUSTER? JR Z,DIRC4 ;1 BYTE LD D,(HL) ;2 BYTES INC HL DIRC4: PUSH HL ;SAVE CLUSTER ADDRESS LD HL,BUFF1 ;CLUSTER ARRAY BASE ADDRESS ADD HL,DE ;USE CLUSTER# AS OFFSET LD A,(HL) ;GET CORRESPONDING VALUE POP HL ;RESTORE CLUSTER ADDRESS CP A,2 ;MORE THAN 1 FILE/CLUSTER? JR C,DIRC5 ;NO LD (IY+15),1 ;YES-SET ERROR FLAG IN FILE ENTRY DIRC5: DJNZ DIRC3 ;REPEAT FOR ALL CLUSTERS ; DIRC6: LD HL,(EPNTR) ;BUMP ENTRY POINTER LD DE,32 ADD HL,DE LD (EPNTR),HL LD HL,(ECNTR) ;DECR ENTRY COUNTER DEC HL LD (ECNTR),HL LD A,L ;CHECK COUNTER VALUE OR A,H JR NZ,DIRC2 ;REPEAT FOR ALL ENTRIES ; DIRC7: LD HL,(FSIZE) ;PUT FILE SIZE LD (IY+13),L ;INTO FILE ENTRY LD (IY+14),H LD HL,(FPNTR) ;BUMP FILE ARRAY POINTER INC HL INC HL LD (FPNTR),HL LD HL,(FCNTR) ;DECR ARRAY COUNTER DEC HL LD (FCNTR),HL LD A,L ;CHECK COUNTER OR A,H JP NZ,DIRC1 ;REPEAT FOR EACH ENTRY IN FILE ARRAY ; LD IY,BUFF1 ;INIT CLUSTER ARRAY POINTER LD HL,0 ;INIT USED BLOCK COUNT LD DE,0 ;INIT TOTAL ERROR COUNT LD BC,1000H ;ARRAY COUNTER DIRC8: LD A,(IY+0) ;GET ARRAY COMPONENT INC IY ;BUMP POINTER OR A,A ;USED? JR Z,DIRC9 ;NO INC HL ;YES-BUMP USED BLOCK COUNT CP A,2 ;ERROR? JR C,DIRC9 ;NO INC DE ;YES-BUMP ERROR COUNT DIRC9: DEC BC ;DECR COUNTER LD A,C ;CHECK COUNTER VALUE OR A,B JR NZ,DIRC8 ;SCAN ENTIRE ARRAY LD (TOTERR),DE ;SAVE ERROR COUNT LD (UBLK),HL ;SAVE USED BLOCK COUNT ; DIRD: LD IY,(BPNTR) ;INIT FILE ARRAY POINTER LD BC,(TOTFIL) ;& ARRAY COUNTER DEC BC LD A,C ;CHECK FOR SINGLE FILE OR A,B ;IN FILE ARRAY JP Z,DIRE ;SKIP SORT FOR SINGLE FILE SET 5,(IX+0) ;SET BUBBLE BIT ; DIRD1: LD L,(IY+0) ;GET 1ST ADDRESS LD H,(IY+1) LD E,(IY+2) ;GET 2ND ADDRESS LD D,(IY+3) CALL NAMTST ;TEST NAMES JR NC,DIRD2 ;SKIP IF NAMES IN ORDER LD (IY+0),E ;ELSE STORE NAMES IN REVERSE LD (IY+1),D LD (IY+2),L LD (IY+3),H RES 5,(IX+0) ;CLEAR BUBBLE BIT DIRD2: INC IY ;BUMP ARRAY POINTER INC IY DEC BC ;DECR ARRAY COUNTER LD A,C ;& CHECK IT OR A,B JR NZ,DIRD1 ;CONTINUE TO END OF ARRAY ; BIT 5,(IX+0) ;ALL IN ORDER? JR Z,DIRD ;NO-DO AGAIN ; DIRE: LD DE,MSG25 ;WRITE OUT HEADER LD C,9 CALL OS ; LD HL,(TOTFIL) ;INIT FILE ARRAY COUNTER LD (FCNTR),HL LD IY,(BPNTR) ;INIT FILE ARRAY POINTER ; DIRE1: LD L,(IY+0) ;GET FILE ADDRESS LD H,(IY+1) INC HL ;POINT TO FILE NAME LD B,8 ;# OF CHARACTERS IN NAME ; DIRE2: LD A,(HL) ;GET CHARACTER CALL CHROUT ;WRITE IT OUT INC HL ;BUMP POINTER DJNZ DIRE2 ;REPEAT FOR FILE NAME ; LD A,SPACE ;WRITE OUT SEPARATOR CALL CHROUT LD B,3 ;# OF CHARACTERS IN TYPE LD D,(HL) ;SAVE 1ST CHARACTER OF EXTENSION PUSH DE ; DIRE3: LD A,(HL) ;GET CHARACTER CALL CHROUT ;WRITE IT OUT INC HL ;BUMP POINTER DJNZ DIRE3 ;REPEAT FOR FILE TYPE ; LD A,(HL) ;GET # OF ENTRIES IN FILE LD (MSG26+6),A ;PUT IN MESSAGE INC HL ;POINT TO FILE SIZE LD E,(HL) ;GET FILE SIZE INC HL LD D,(HL) LD A,(BSH) ;GET SHIFT FACTOR SUB A,3 ;ADJUST JR Z,DIRE5 ;SKIP IF SIZE=KBYTES LD B,A ;ELSE SET COUNTER EX DE,HL ;SAVE POINTER DIRE4: ADD HL,HL ;KBYTES=SIZE * (2 ** (BSH-3)) DJNZ DIRE4 EX DE,HL ;RESTORE REGISTERS DIRE5: LD (MSG26+2),DE ;KBYTES TO MESSAGE LD DE,MSG26 ;WRITE OUT MESSAGE LD C,9 CALL OS ; POP BC ;RESTORE 1ST CHARACTER OF EXTENSION BIT 7,B ;TEST PROTECT BIT LD C,9 ;& SETUP TO WRITE MESSAGE LD DE,MSG35 ;R/W CALL Z,OS ;SEND READ/WRITE LABEL LD DE,MSG36 ;R/O CALL NZ,OS ;SEND READ/ONLY LABEL ; INC HL ;POINT TO ERROR FLAG LD DE,MSG28 ;ERROR MESSAGE POINTER BIT 0,(HL) ;ERROR IN FILE? CALL NZ,OS ;YES-WRITE OUT MESSAGE ; LD DE,MSG29 ;WRITE OUT CRLF CALL OS ; INC IY ;BUMP FILE POINTER INC IY LD HL,(FCNTR) ;DECR FILE COUNTER DEC HL LD (FCNTR),HL LD A,L ;CHECK COUNTER OR A,H JR NZ,DIRE1 ;REPEAT FOR ALL FILES ; LD HL,(DRM) ;GET TOTAL ENTRY COUNT FOR DISK INC HL ;SET FOR ACTUAL NUMBER LD (MSG31+10),HL ;PUT INTO MESSAGE LD DE,(UENT) ;GET USED ENTRY COUNT LD (MSG31+14),DE ;PUT INTO MESSAGE OR A,A ;CLEAR CARRY SBC HL,DE ;GET ENTRIES LEFT LD (MSG31+18),HL ;PUT INTO MESSAGE ; LD HL,(DSM) ;GET TOTAL DISK BLOCK COUNT INC HL ;ADJUST FOR ACTUAL NUMBER LD A,(BSH) ;GET SHIFT FACTER SUB A,3 ;ADJUST JR Z,DIRE7 ;SKIP IF BLOCK COUNT=KBYTES LD B,A ;ELSE SETUP COUNTER DIRE6: ADD HL,HL ;KBYTES=BLOCKS * (2 ** (BSH-3)) DJNZ DIRE6 DIRE7: LD (MSG32+10),HL ;PUT TOTAL INTO MESSAGE LD DE,(UBLK) ;GET USED BLOCK COUNT OR A,A ;ANY ADJUST? JR Z,DIRE9 ;NO LD B,A ;YES-SETUP COUNTER EX DE,HL ;& REGISTERS DIRE8: ADD HL,HL ;KBYTES=BLOCKS * (2 ** (BSH-3)) DJNZ DIRE8 EX DE,HL ;RESTORE REGISTERS DIRE9: LD (MSG32+14),DE ;PUT USED COUNT INTO MESSAGE OR A,A ;CLEAR CARRY SBC HL,DE ;GET KBYTES LEFT LD (MSG32+18),HL ;& PUT INTO MESSAGE ; LD HL,(TOTFIL) ;PUT TOTAL FILE COUNT LD (MSG33+10),HL ;INTO MESSAGE ; LD HL,(TOTERR) ;PUT TOTAL ERROR COUNT LD (MSG34+10),HL ;INTO MESSAGE ; LD A,(FCB1) ;GET DISK# OR A,40H ;ADD ASCII BITS LD (MSG30+7),A ;PUT INTO MESSAGE ; LD DE,MSG30 ;USE AS RETURN MESSAGE RET ; ;********************************************************************** ; ; batch: check for less than 2 file names in command line ; ; if one file specified ; then copy file into batch command file ; and enable batch mode ; ; if no files in command line ; then check program return code ; ; if program return code=http://cpmarchives.classiccmp.org/cpm/Software/rlee/O/OCCO/MRS-OS/0 (no batch running) ; then get batch commands from console ; and save them in the batch command file ; ; if program return code<>0 (batch running) ; then get command line corresponding to the ; program return code value ; if no lines left in the batch command file ; then set program return code=0 ; else put line into MRS command line buffer ; and increment program return code ; and call MRS to execute command line ; ;********************************************************************** ; ; BATCH: LD DE,MSG1 ;ERROR MESSAGE BIT 2,(IX+0) ;2 FILES SPECIFIED? RET NZ ;YES-ERROR LD HL,BUFF1 ;INIT COMMAND BUFFER LD DE,BUFF1+1 LD BC,2000H LD (HL),EOF LDIR LD HL,BTHNAM ;SETUP COMMAND FILE NAME LD DE,FCB2 LD BC,12 LDIR BIT 1,(IX+0) ;WAS FILE SPECIFIED IN CMD LINE? JP Z,BATCH1 ;NO ; LD A,(FCB1) ;YES-USE SAME DISK LD (FCB2),A ;FOR COMMAND FILE LD DE,FCB1 ;OPEN USER COMMAND FILE LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR LD DE,FCB2 ;CREATE BATCH COMMAND FILE LD C,22 CALL OS LD DE,MSG7 ;ERROR MESSAGE AND A,80H ;DIRECTORY FULL? RET NZ ;YES-DONE ; LD HL,FCB1 ;READ USER COMMAND FILE LD DE,BUFF1 CALL RDBUF INC (IX+3) ;ADD EXTRA SECTOR LD HL,FCB2 ;WRITE COMMANDS TO BATCH CMD FILE LD DE,BUFF1 CALL WRBUF LD DE,MSG8 ;ERROR MESSAGE RET NZ ;DONE IF WRITE ERROR LD DE,FCB2 ;CLOSE BATCH COMMAND FILE LD C,16 CALL OS LD E,1 ;SET PROGRAM RETURN CODE LD C,147 ;FOR 1ST COMMAND CALL OS LD DE,MSGD ;RETURN MESSAGE RET ; BATCH1: LD E,0 ;READ CURRENT PROGRAM RET CODE LD C,147 ;& SET TO ZERO FOR NOW CALL OS OR A,A ;BATCH NOW RUNNING? JP NZ,BATCH4 ;YES-SKIP TO BATCH PROCESSOR LD DE,FCB2 ;CREATE NEW BATCH LD C,22 ;COMMAND FILE CALL OS LD DE,MSG7 ;ERROR MESSAGE AND A,80H ;DIRECTORY FULL? RET NZ ;YES-DONE LD HL,BUFF1 ;INIT COMMAND POINTER LD (CNTR1),HL ; BATCH2: LD DE,MSG38 ;SEND BATCH PROMPT LD C,9 CALL OS LD DE,CMDLIN ;READ COMMAND LINE LD C,10 CALL OS LD A,LF ;ECHO LINE FEED CALL CHROUT LD A,(CMDLIN+1) ;CMD LINE LENGTH OR A,A ;ANY INPUT? JR Z,BATCH3 ;NO-SKIP LOOP LD C,A ;TRANSFER SIZE LD B,0 LD HL,CMDLIN+2 ;TRANSFER CMD TO BUFFER LD DE,(CNTR1) LDIR LD HL,MSG29 ;ADD CRLF TO END OF MESSAGE LD C,2 LDIR LD (CNTR1),DE ;SAVE POINTER TO NEXT CMD LINE JR BATCH2 ;CONTINUE INPUT LOOP ; BATCH3: LD HL,(CNTR1) ;DETERMINE SIZE OF TOTAL INPUT LD DE,BUFF1 SBC HL,DE ADD HL,HL ;H=SIZE/128=# OF SECTORS INC H ;ADD EXTRA SECTOR LD (IX+3),H ;INIT SECTOR WRITE COUNT LD HL,FCB2 ;WRITE BUFFER TO LD DE,BUFF1 ;BATCH COMMAND FILE CALL WRBUF LD DE,MSG8 ;ERROR MESSAGE RET NZ ;DONE IF WRITE ERROR LD DE,FCB2 ;CLOSE COMMAND FILE LD C,16 CALL OS LD E,1 ;SET PROGRAM RETURN CODE LD C,147 ;FOR 1ST COMMAND IN FILE CALL OS LD DE,MSG39 ;BATCH MESSAGE RET ; BATCH4: LD (IX+10),A ;SAVE PROGRAM RETURN CODE LD (IX+1),A ;& USE FOR COUNTER LD DE,FCB2 ;OPEN COMMAND FILE LD C,15 CALL OS LD DE,MSG4 ;ERROR MESSAGE AND A,80H ;FILE FOUND? RET NZ ;NO-ERROR LD HL,FCB2 ;READ CMD FILE INTO BUFFER LD DE,BUFF1 CALL RDBUF ; LD HL,BUFF1 ;LINE POINTER LD BC,2000H ;MAX COUNT LD A,LF ;END OF LINE CHAR BATCH5: DEC (IX+1) ;DECR COMMAND COUNT JR Z,BATCH6 ;SKIP IF AT LINE CPIR ;FIND END OF NEXT LINE JR Z,BATCH5 ;CONTINUE LOOP WHILE EOL FOUND BATCH6: LD A,(HL) ;GET NEXT CHAR CP A,EOF ;END OF FILE? JR NZ,BATCH7 ;NO LD DE,FCB2 ;YES-DELETE COMMAND FILE LD C,19 CALL OS LD DE,MSG40 ;BATCH END MESSAGE RET ; BATCH7: LD DE,CMDLIN+2 ;TRANSFER CMD LINE LD BC,80 ;TO CMD LINE BUFFER LDIR ;FOR OS LD HL,CMDLIN+2 ;FIND END OF CMD LINE LD BC,80 LD A,LF ;LAST CHAR CPIR LD A,78 ;DETERMINE CLINE LENGTH SUB A,C LD (CMDLIN+1),A ;INIT CMD BUFFER LD (HL),'$' ;BUFFER OUTPUT TERMINATING CHAR PUSH HL ;SAVE EOL ADDRESS LD DE,CMDLIN+2 ;WRITE COMMAND LINE LD C,9 CALL OS POP IY ;RESTORE EOL ADDRESS LD (IY-2),0 ;SET END OF BUFFER CHAR LD E,(IX+10) ;GET PROGRAM RETURN CODE INC E ;POINT TO NEXT CMD LD C,147 ;INIT IN OS CALL OS LD C,136 ;EXECUTE COMMAND LINE CALL OS JP 0 ; ;********************************************************************** ; ; write data block in hexadecimal format: ; ; HL = printed address of data ; DE = actual address of data ; ;********************************************************************** ; ; WRBLK: PUSH BC ;SAVE REGISTER LD C,8 ;LINE COUNT WRBLK1: LD A,CR ;WRITE CARRAGE RETURN CALL CHROUT LD A,LF ;WRITE LINE FEED CALL CHROUT LD A,H ;WRITE ADDRESS MSB'S CALL HEXOUT LD A,L ;WRITE ADDRESS LSB'S CALL HEXOUT LD A,TAB ;WRITE ADDRESS/DATA SEPARATOR CALL CHROUT PUSH DE ;SAVE DATA POINTER LD B,16 ;CHARACTER COUNT WRBLK2: LD A,(DE) ;WRITE CHAR IN HEX CALL HEXOUT LD A,20H ;WRITE DATA SPACER CALL CHROUT INC DE ;BUMP DATA POINTER INC HL ;& ADDRESS DJNZ WRBLK2 ;CONTINUE WRITE LOOP ; LD B,4 ;WRITE HEX/ASCII SEPARATOR WRBLK3: LD A,20H CALL CHROUT DJNZ WRBLK3 ; POP DE ;RESTORE ORIGINAL POINTER LD B,16 ;CHARACTER COUNT WRBLK4: LD A,(DE) ;PRINT CHAR IF CP A,20H ;IN PRINTABLE RANGE JR NC,WRBLK5 LD A,'.' ;ELSE USE DEFAULT CHAR JR WRBLK6 WRBLK5: CP A,7FH JR C,WRBLK6 LD A,'.' WRBLK6: CALL CHROUT ;WRITE CHAR INC DE ;BUMP DATA POINTER DJNZ WRBLK4 ;CONTINUE WRITE LOOP DEC C ;LINE COUNT JR NZ,WRBLK1 ;CONTINUE WRITE LINE LOOP POP BC ;THEN RESTORE REGISTER RET ;& DONE ; ;********************************************************************** ; ; READ UP TO 8K BYTES OF FILE ; ;********************************************************************** ; ; RDBUF: LD (CNTR1),HL ;SAVE FCB ADDRESS LD (CNTR2),DE ;SAVE BUFFER ADDRESS LD (IX+2),0 ;INIT SECTOR COUNT RDBUF2: LD DE,(CNTR2) ;GET CURRENT BUFFER ADDR LD HL,128 ;BUMP BUFFER ADDR ADD HL,DE LD (CNTR2),HL ;& SAVE FOR NEXT LOOP LD C,26 ;SET BUFFER ADDRESS CALL OS LD DE,(CNTR1) ;READ SECTOR LD C,20 CALL OS OR A,A ;SUCCESSFUL READ? JR NZ,RDBUF4 ;NO-DONE INC (IX+2) ;YES-BUMP SECTOR COUNT BIT 6,(IX+2) ;64 SECTORS YET? JR Z,RDBUF2 ;NO-CONTINUE READING RDBUF4: LD A,(IX+2) ;COPY SECTOR COUNT LD (IX+3),A OR A,A ;UPDATE 'Z' FLAG RET ;********************************************************************** ; ; WRITE BUFFER TO FILE ; ;********************************************************************** ; ; WRBUF: LD (CNTR1),HL ;SAVE FCB ADDRESS LD (CNTR2),DE ;SAVE BUFFER ADDRESS LD A,(IX+3) ;GET SECTOR COUNT OR A,A ;ANY TO WRITE? RET Z ;NO-DONE WRBUF2: LD DE,(CNTR2) ;NO-GET BUFFER ADDRESS LD HL,128 ;BUMP ADDRESS ADD HL,DE LD (CNTR2),HL ;& SAVE FOR NEXT LOOP LD C,26 ;SET BUFFER ADDRESS CALL OS LD DE,(CNTR1) ;WRITE DATA TO FILE LD C,21 CALL OS OR A,A ;WRITE SUCCESSFUL? RET NZ ;NO-DONE DEC (IX+3) ;YES-DECR SECTOR COUNT JR NZ,WRBUF2 ;CONTINUE WRITE LOOP RET ;DONE ; ;********************************************************************** ; ; boot: calculate address of cold boot vector in MRSIO jump table ; and vector to it ; ;********************************************************************** ; ; BOOT: LD HL,(1) ;GET ADDRESS OF WARM BOOT VECTOR DEC HL ;COLD BOOT ADDRESS = DEC HL ; WARM BOOT ADDRESS - 3 DEC HL JP (HL) ;VECTOR TO COLD BOOT IN MRSIO ;********************************************************************** ; ; GET DISK STATUS & RETURN WITH TOTAL RECORDS ON DISK IN 'HL' ; ;********************************************************************** ; ; GETSTA: AND A,0FH ;STRIP ASCII JR NZ,GETSTB ;SKIP IF NOT CURRENT DISK LD A,(CURDSK) ;ELSE GET CURRENT DISK# INC A ;SET TO FCB# GETSTB: DEC A ;SET TO SYSTEM# LD E,A ;SELECT DISK LD C,14 CALL OS LD C,31 ;GET DPB ADDRESS CALL OS PUSH HL ;IY=DPB ADDRESS POP IY ; LD L,(IY+5) ;GET DSM LD H,(IY+6) INC HL ;ADJUST FOR TOTAL RECORD COUNT LD B,(IY+2) ;GET BSH GETSTC: ADD HL,HL ;TOTAL RECORDS= (DSM+1) * (2 ** BSH) DJNZ GETSTC LD E,(IY+0) ;GET SPT LD D,(IY+1) RET ;DONE ;********************************************************************** ; ; INDIRECT CALL FROM (HL) ; ;********************************************************************** ; ; INDCAL: JP (HL) ; ;********************************************************************** ;********************************************************************** ;********************************************************************** ;********************************************************************** ; ; ; ; SSP DATA ; ; ; ;********************************************************************** ;********************************************************************** ;********************************************************************** ;********************************************************************** ; ; ; STATUS ARRAY ; SYSTAT: DB 80H ;FLAGS (0) DB 0 ;COUNTER (1) DB 0 ;READ SECTOR COUNTER (2) DB 0 ;WRITE SECTOR COUNTER (3) DB 0 ;LINKED CLUSTER COUNT (4) DB 0 ;DIRECTORY ENTRY COUNT (5) DB 0 ;DIRECTORY FILE COUNT (6) DB 0 ;DISK# (7) DB 0 ;DISK# (8) DB 0 ;TRACK# (9) DB 0 ;COUNTER (10) ; ; MISC DATA ; CNTR1: DW 0 CNTR2: DW 0 CNTR3: DW 0 CURDSK: DB 0 ;TEMP STORAGE FOR CURRENT DISK# BPNTR: DW 0 ;BUFFER POINTER RCDCNT: DW 0 ;RECORD COUNTER SECNT: DW 0 ;SECTOR COUNTER TRKCNT: DW 0 ;TRACK COUNTER TOTRCD: DW 0 ;DISK SIZE IN RECORDS SECTRK: DW 0 ;SECTORS/TRACK (SPT) UENT: DW 0 ;USED DISK ENTRIES ECNTR: DW 0 ;ENTRY COUNTER EPNTR: DW 0 ;ENTRY ARRAY POINTER FCNTR: DW 0 ;FILE ARRAY COUNTER FPNTR: DW 0 ;FILE ARRAY POINTER FSIZE: DW 0 ;FILE SIZE TOTFIL: DW 0 ;NUMBER OF FILES ON DISK TOTERR: DW 0 ;DIRECTORY ERROR COUNT UBLK: DW 0 ;NUMBER OF USED BLOCKS IN DIRECTORY SPT: DW 0 ;SECTORS/TRACK BSH: DB 0 ;SHIFT FACTOR BLM: DB 0 ;MASK EXM: DB 0 ;EXTENT MASK DSM: DW 0 ;DISK SIZE DRM: DW 0 ;DIRECTORY SIZE AL0: DW 0 ;ALLOCATION BITS CKS: DW 0 ;CHECK VECTOR SIZE OFF: DW 0 ;NUMBER OF SYSTEM TRACKS ; DIRNAM: DB ' DIR ' BTHNAM: DB 0,'BATCH ###' ; ; CMD TABLE ; CMDTAB: DB ' END ' DW SYSRET DB ' ERA ' DW ERA DB ' REN ' DW REN DB ' BOOT ' DW BOOT DB ' HELP ' DW HELP DB ' TYPE ' DW TYPE DB ' DUMP ' DW DUMP DB ' SAVE ' DW SAVE DB ' XFER ' DW XFER DB ' CMPR ' DW CMPR DB ' MERGE ' DW MERGE DB ' INIT ' DW INIT DB ' COPY ' DW COPY DB ' DIR ' DW DIR DB ' PATCH ' DW PATCH DB ' BATCH ' DW BATCH DB ' PRINT ' DW PRINT DB ' PDUMP ' DW PDUMP DB ' PDIR ' DW PDIR DB ' PROTECT ' DW PROTCT DB ' RELEASE ' DW RELEAS ; ;********************************************************************** ; ; SSP MESSAGES ; ;********************************************************************** ; ; PRMPT: DB 13,10,'SSP. >$' MSG0: DB 'command not recognized : type HELP for menu$' MSG1: DB 'illegal number of files specified$' MSG2: DB 82H,0,0,' directory entries ERASED$' MSG3: DB 82H,0,0,' directory entries RENAMED$' MSG4: DB 'specified file not found$' MSG5: DB '4 digit HEX ADDRESS not found$' MSG6: DB 82H,0,0,' Kbytes SAVED$' MSG7: DB 'directory space FULL$' MSG8: DB 'disk space FULL$' MSG9: DB 'CONTROL-C has aborted the current procedure$' MSG10: DB 'xfer completed - verify begun....$' MSG11: DB 'compare FAILED : files were of differing lengths$' MSG12: DB 82H,0,0,' records COMPARED with ',82H,0,0,' ERROR(S)$' MSG13: DB 'file MERGE completed$' MSG14: DB 82H,0,0,' records written to system tracks$' MSG15: DB 'ready to copy disk to disk (press Y/N)? $' MSG16: DB 13,'track ',82H,0,0,20H,36 MSG17: DB 'ERROR on disk read$' MSG18: DB 'ERROR on disk write$' MSG19: DB 'disk COPY completed$' MSG20: DB 'valid record range is 0 to ',82H,0,0,36 MSG21: DB 'file contains NO data$' MSG22: DB 'record ',82H,0,0,36 MSG23: DB 13,10,'Patch>$' MSG24: DB '?...$' MSG25: DB 13,10,'Disk Directory:',13,10,13,10,36 MSG26: DB 9,82H,0,0,'/',82H,0,0,' Kbytes/entries$' MSG28: DB 9,'*** allocation error ***$' MSG29: DB 13,10,36 MSG30: DB 13,10,'DISK ',9,9,'Total',9,'Used',9,'Left',13,10 MSG31: DB 'Entries',9,9,82H,0,0,9,82H,0,0,9,82H,0,0,13,10 MSG32: DB 'Kbytes ',9,9,82H,0,0,9,82H,0,0,9,82H,0,0,13,10 MSG33: DB 'Files ',9,9,82H,0,0,13,10 MSG34: DB 'Errors ',9,9,82H,0,0,13,10,36 MSG35: DB 9,'R/W$' MSG36: DB 9,'R/O$' MSG37: DB 'transfer ERROR : file names are identical$' MSG38: DB 'Batch>$' MSG39: DB '*** Batch mode ENABLED ***',13,10,36 MSG40: DB 7,'*** Batch processing COMPLETED ***',13,10,36 MSG41: DB 13,10,'NO entries found in disk directory',13,10,36 MSG42: DB 'Disks are NOT identical - no copy attempted',13,10,36 MSG43: DB 'DISK is now PROTECTED$' MSG44: DB 82H,0,0,' entries are PROTECTED$' MSG45: DB 82H,0,0,' entries now READ/WRITE$' MSGD: DB '$' ; MSGH: DB 13,10,13,10 DB 'SYSTEM SUPPORT PROCEDURES (SSP) MENU',13,10,13,10 DB 'COMMAND----PARAMETERS----USE',13,10 DB 'END none terminate SSP',13,10 DB 'BOOT none vector to cold boot',13,10 DB 'TYPE file display file',13,10 DB 'PRINT file print file',13,10 DB 'DUMP file,hxaddr display file in hex',13,10 DB 'PDUMP file,hxaddr print file in hex',13,10 DB 'REN file1,file2 rename file2',13,10 DB 'ERA file erase file',13,10 DB 'PATCH disk/file edit in hex',13,10 DB 'SAVE file,ksize save user memory',13,10 DB 'INIT disk,file init disk OS space',13,10 DB 'DIR display the directory',13,10 DB 'PDIR print the directory',13,10 DB 'XFER file1,file2 transfer files',13,10 DB 'CMPR file1,file2 compare files',13,10 DB 'COPY disk1,disk2 transfer disk2 to disk1',13,10 DB 'MERGE file1,file2 merge files (ASCII)',13,10 DB 'BATCH execute batch mode',13,10 DB 'PROTECT disk/file protect disk/file',13,10 DB 'RELEASE file set file to read/write',13,10 DB 36 ; MSGPH: DB 13,10,13,10 DB 'PATCH commands',13,10,13,10 DB 'Rrec# read record (rec#)',13,10 DB 'Wrec# write record (rec#)',13,10 DB 'Moffset,h#,.. modify offset bytes by hex values',13,10 DB 'Aoffset,string place ASCII string at offset',13,10 DB 'Ihex# initialize block to hex#',13,10 DB 'H display help message',13,10 DB 'E end PATCH & return to SSP exec',13,10,36 ; ; ; FCB'S ; CMDFCB: DS 12 ;COMMAND WORD FCB FCB1: DS 36 ;FILE1 FCB FCB2: DS 36 ;FILE2 FCB ; ; ; END SSP