TITLE DEBUG 26 DEC 80 10:20 ;************************************************************* ; ; This DEBUG program is a stand-alone program to allow ; programs to be loaded and debugged by modification & ; by use of breakpoints. It is similar to the PHIMON ; DTx program, but allows I/O ports to be examined/loaded, ; and display mode to be changed while in the program and ; search through memory for a particular string of bytes. ; It also allows Files to be loaded via the directory or ; a particular block or blocks to be read from or written ; to a tape. ; ; NOTE: This program does use the I/O proms. ; ;************************************************************* FORM ; ; EXTERNAL ROUTINES ; REWIND: EQU 0F41EH WRITF: EQU 0F415H SETDRV: EQU 0F40CH STOP: EQU 0F418H SETDMA: EQU 0F403H SETBID: EQU 0F406H SETCNT: EQU 0F409H READF: EQU 0F412H MSPACE: EQU 0FC15H CRLFOT: EQU 0FC1BH CO: EQU 0FC09H CI: EQU 0FC03H EDITR: EQU 0FC12H ; FORM ; ; MASKS ; OCTMSK: EQU 00000111B HEXMSK: EQU 00001111B CTLMSK: EQU 01100000B CUCMSK: EQU 01000000B ; ; ASCII CONSTANTS ; LF: EQU 0AH FORMF: EQU 0CH CR: EQU 0DH AESC: EQU 1BH ASPACE: EQU 20H AMINUS: EQU 2DH APEROD: EQU 2EH ;'.' ASLASH: EQU 2FH ;'/' AZERO: EQU '0' AEIGHT: EQU '8' ANINE: EQU '9' COLON: EQU ':' SCOLON: EQU ';' ALT: EQU '<' AEQUAL: EQU '=' AGT: EQU '>' AX: EQU 'X' AY: EQU 'Y' LCASE: EQU 'a' LCOFFS: EQU 20H CESC: EQU AESC+CUCMSK ; ; CONSTANTS ; HOFSET: EQU 7 ZERO: EQU 0 ONE: EQU 1 TEN: EQU 10D WRTEN: EQU 1 PRVIEW: EQU -8D DMPCNT: EQU 9D OPNMOD: EQU 1 REGMOD: EQU -1 FLGSP: EQU 2 REGCNT: EQU 3 RPSP: EQU 2 JMP: EQU 0C3H RST7: EQU 0FFH NOBRK: EQU -1 RCNT: EQU 8D SETMSK: EQU 1 BUFMAX: EQU 80D ENTMOD: EQU -1 ; ; COMPILE TIME PARAMETERS ; BPVADR: EQU 0E016H ABORT: EQU 0 ISTACK: EQU 0C080H ; FORM ;************************************************************* ; ORG 100H ; DEBUG: JP DTX ;DEBUG VECTOR ; ; I/O VECTORS ; CONIN: JP CI CONOUT: JP CO CRLF: JP CRLFOT MLTSPC: JP MSPACE EDITOR: JP EDITR ; BPVECT: DW BPVADR ;RESTART 56D BREAKPOINT VECTOR LOC'N ABOVCT: DW ABORT ;SYSTEM RETURN VECTOR SYSSTK: DW ISTACK ;SYSTEM STACK POINTER ; ; CONVERT BINARY BYTE IN A TO ASCII & DISPLAY IT ; PRNUMB: OR A ;CLEAR CARRY PUSH AF LD A,(NUMBAS) ;IF BASE FLAGE=0 THEN HEX OUTPUT OR A JR Z,HXNUMB POP AF ;RESTORE # CALL PRDIG ;CONVERT 1ST DIGIT TO ASCII OCTAL CALL PRDIG ;CONVERT 2ND DIGIT PRDIG: RLA ;ROTATE MSD TO LSD RLA ;NOTE, THE 1ST TIME THROUGH, CARRY WAS RLA ;0, MAKING THE 1ST DIGIT MAX OF 3 PUSH AF ;SAVE IT AND OCTMSK ;MASK OUT UPPER BITS ADD AZERO ;CONVERT TO ASCII CALL CONOUT POP AF ;RESTORE # RET ;LAST TIME,RETURNS TO CALLING PGM ; HXNUMB: POP AF ;RESTORE # RLA ;PUT MSB IN CARRY CALL PRHXDG PRHXDG: RLA ;PUT MSD IN LSD RLA RLA RLA PUSH AF ;SAVE IT AND HEXMSK ;MASK OUT UPPER BITS CP TEN ;IF NOT ALPHA THEN OK AS IS JR C,NTALPH ADD HOFSET ;ELSE CONVERT 10-15 TO 'A-F' NTALPH: ADD AZERO ;CONVERT TO ASCII CALL CONOUT POP AF ;RESTORE # RET ; ; BREAKPOINT 16 BIT BINARY TO ASCII CONVERSION SUBR'N ; PASS IN 16 BIT VALUE IN HL. IF ZERO, 'NONE IS ; DISPLAYED. ; CHKNON: LD A,L ;IF HL=FFFFH THEN OUTPUT 'NONE' (NO ; BREAKPOINT) AND H INC A JR Z,NONE ; ; OUTPUT 16 BIT NUMBER IN HL TO CONSOLE DEVICE ; PRTDBL: LD A,H ;DISPLAY H CALL PRNUMB ; ; OUTPUT 8 BIT VALUE IN L TO CONSOLE DEVICE ; PRTSGL: LD A,L ;OUT L CALL PRNUMB RET ; NONE: LD HL,NONMSG ;DISPLAY 'NONE' CALL EDITOR RET ; ; TAB PER BASE SUBR- COMPUTES PROPER NUMBER OF LEADING ; SPACES TO VALUE. ; EXIT - SPACE COUNT IN A ; OHTAB: LD A,(NUMBAS) ;COMPUTE SPACE COUNT CPL ADD 3 PUSH AF CALL MLTSPC ;OUTPUT SPACES POP AF RET ; ; DUMP LOCATION SUBROUTINE ; CONTENTS OF HL ARE DISPLAYED FOLLOWED BY A '/' AND ; FOLLOWED BY THE CONTENTS OF THE LOCATION POINTED TO ; BY HL ; DMPLOC: CALL PRTDBL ;DISPLAY HL LD A,ASLASH CALL CONOUT LD A,(HL) ;FETCH DATA CALL PRNUMB ;DISPLAY CONTENTS RET ; ; NONMSG: DB 'NONE ',0 FLGTAB: DB 'S',80H,'Z',40H,'H',10H,'P',4,'N',2,'C',1,0 REGTAB: DB 'FACBEDLH' ; ; GET NUMBER IN DE UNTIL NON-BASE CHAR ENCOUNTERED ; WXIT - LAST CHAR IN B, NUMBER IN DE ; GETNUM: LD HL,ZERO ;CLEAR ACCUMULATOR LD A,(NUMBAS) ;IF HEX BASE THEN INPUT HEX OR A JR Z,HEXIN ;0= HEX, 1= OCTAL LD HL,ZERO LD C,H ;RESET WRITE ENABLE FLAG PUSH AF ;SAVE MODE DIGUP: CALL CONIN ;INPUT DATA LD B,A CALL CONOUT LD A,B CP AEIGHT ;IF <> "0-7" THEN TEST FOR COMMAND JR NC,NOTDIG SUB AZERO JR C,NOTDIG LD B,A ;SAVE DIGIT POP AF ;RESTORE FLAGS ADD HL,HL ;SHIFT OLD DIGITS OVER ONE DIGIT ADD HL,HL ADD HL,HL PUSH AF ;SAVE FLAGS LD A,B ;RESTORE DIGIT ADD L ;PUT NEW DIGIT IN DATA REG LD L,A LD C,WRTEN ;SET WRITE ENABLE JP DIGUP ;NEXT CHAR ; HEXIN: CALL CONIN CP LCASE ;IF NOT LOWER CASE THEN OK AS IS JR C,UC SUB LCOFFS ;ELSE CONVERT TO UPPER CASE UC: LD B,A CALL CONOUT LD A,B CP 'F'+1 ;IF >'F' THEN NOT HEX JR NC,NTHDIG CP ANINE+1 ;ELSE IF <= '9' THEN OK JR C,NALPHA SUB HOFSET ;ELSE CONVERT 'A-F' TO 10-15 NALPHA: SUB AZERO ;IF <'0' THEN NOT DIGIT JR C,NTHDIG ADD HL,HL ;SHIFT OLD DIGIT OVER 1 DIGIT ADD HL,HL ADD HL,HL ADD HL,HL ADD L ;ADD NEW DIGIT LD L,A LD C,WRTEN ;SET WRITE ENABLE JR HEXIN ; ; NOT HEX DIGIT FALLOUT. MUST BE COMMAND/INVALID CHAR ; NOTDIG: POP AF ;COMPENSATE FOR SPLIT OCTAL RR H NTHDIG: EX DE,HL ;SAVE DATA REG RET ; ; MAIN PROGRAM START ; DTX: XOR A ;INITIALIZE LD (DSPMOD),A LD (MODBRK),A LD SP,(SYSSTK) ;SET STACK LD HL,NOBRK ;CLEAR PENDING BREAKPOINT LD (RETADR),HL CLEAR: CALL PRMSGS ;DISPLAY BREAKPOINT,RETURN ADDRS IN: CALL GETNUM ;INPUT NUMBER,COMMAND LD HL,DTXTAB ;SET COMMAND TABLE PTR LD A,B ;B STILL HAS LAST CHAR INPUTTED AND CTLMSK ;IF NOT CONTROL CHAR THEN OK AS IS LD A,B JR NZ,NOTC OR CUCMSK ;ELSE MAKE CTRL CHAR INTO UPPER CASE NOTC: LD B,(HL) ;GET TABLE ELEMENT COUNT DTXNXT: INC HL ;PTR CP (HL) ;TEST FOR MATCH INC HL ;POINT TO JP ADDR IN TABLE JR Z,FOUND INC HL DJNZ DTXNXT END: LD A,(DSPMOD) ;TEST PRESENT MODE OR A JP Z,CLEAR ;CLOSED MODE JP M,REGSTR ;REGISTER DISPLAY MODE DUMP1: LD HL,(LOCATN) ;FETCH MEM LOCATION POINTER DUMP2: LD (LOCATN),HL ;SET LOCATION POINTER LD DE,PRVIEW ;OUTPUT PREVIOUS LOCATIONS ADD HL,DE PUSH HL ;SAVE POINTER CALL PRMSGS ;DISP. BP, RET POP HL LD C,DMPCNT ;SET COUNT NXTDMP: CALL PRTDBL ;OUTPUT ADDR CALL SPACE LD A,ASLASH ;OUTPUT '/' CALL CONOUT CALL SPACE LD A,(HL) ;OUTPUT CURRENT VALUE OF LOCATION CALL PRNUMB DEC C ;DUMP COUNT -1 JR Z,ENDUMP INC HL ;ADVANCE POINTER CALL CRLF JP NXTDMP ; ENDUMP: LD A,AEQUAL ;OUTPUT '=' CALL CONOUT LD A,OPNMOD ;SET MEMORY OPENED MODE LD (DSPMOD),A JP IN ; ; COMMAND FOUND - GET ADDR FROM TABLE & GO TO IT ; FOUND: PUSH DE LD E,(HL) ;GET ADDR INC HL LD D,(HL) EX DE,HL POP DE XOR A JP (HL) ;SERVICE COMMAND ; ; THIS ROUTINE IS ENTERED UPON BREAKPOINT OCCURRANCE ; ENCBRK: LD (USRSTK),SP ;SAVE USER STACK PTR LD SP,DTXSTK ;SET BREAKPOINT STACK PUSH HL ;SAVE REGS PUSH DE PUSH BC PUSH AF LD HL,(USRSTK) ;GET RETURN ADDR LD A,(HL) INC HL LD H,(HL) LD L,A DEC HL LD (RETADR),HL ;SET POINTER XOR A ;SET REGISTER SET POINTER TO MAIN LD (REGSET),A INC A ;SET IN BP FLAG LD (MODBRK),A ; ; REGISTER DISPLAY ROUTINE ; REGSTR: CALL PRMSGS ;DISP BP, RET LD HL,SETMSG ;DISP 'REG SET:' CALL EDITOR LD A,(REGSET) ;DETERMINE PRESENT REGISTER SET OR A JR Z,MAINST LD HL,ALTMSG ;DISP 'ALTERNATE' CALL EDITOR JR FINSET ; MAINST: LD HL,MANMSG ;DISP 'MAIN' CALL EDITOR FINSET: LD HL,FLGMSG ;DISP 'FLAGS:' CALL EDITOR LD HL,ZERO LD A,(REGMOD AND 0FFH) ;SET REGISTER DISPLAY MODE LD (DSPMOD),A ADD HL,SP ;FETCH SP VALUE LD DE,FLGTAB ;SET TABLE POINTER FLAGUP: LD A,(DE) ;FETCH FLAG CHAR INC DE ;POINTER +1 OR A ;TEST FOR END OF TABLE JR Z,REG2 CALL CONOUT ;OUTPUT FLAG CHAR FROM TABLE LD A,(DE) ;FETCH FLAG MASK INC DE ;POINT TO NEXT FLAG CHAR AND (HL) ;MASK OUT UNWANTED FALGS LD A,AZERO JR Z,FLAG0 ;IF MASKED FLAG =0, OUTPUT '0' INC A ;IF MASKED FLAG =1, OUTPUT '1' FLAG0: CALL CONOUT LD A,FLGSP ;OUTPUT SPACES BETWEEN FLAGS CALL MLTSPC JR FLAGUP ; REG2: PUSH HL ;PUSH STACK POINTER VALUE LD HL,REGMSG ;DISP 'REGISTERS:' CALL EDITOR POP HL ;POP STACK POINTER VALUE & INC TO A INC HL ;VALUE CALL OHTAB LD A,(HL) ;OUTPUT ACCUMULATOR VALUE FROM STACK CALL PRNUMB LD C,REGCNT ;SET REGISTER PAIR COUNT REGUP: INC HL ;POINT TO NEXT REGISTER DATA LD D,(HL) ;SAVE LOW REG OF PAIR INC HL CALL OHTAB LD A,(HL) ;OUTPUT HIGH REG OF PAIR CALL PRNUMB CALL OHTAB LD A,D ;OUTPUT LOW REG OF PAIR CALL PRNUMB DEC C ;COUNT -1 JR NZ,REGUP ;NXT REG PAIR ; CALL OHTAB LD A,I ;OUTPUT INTERRUPT REG CALL PRNUMB LD HL,STKMSG ;DISP 'STACK PTR' CALL EDITOR CALL OHTAB PUSH AF ;SAVE SPACE COUNT LD HL,(USRSTK) INC HL ;CORRECT STACK PTR TO VALUE AT BREAK INC HL CALL PRTDBL POP AF ADD RPSP PUSH AF CALL MLTSPC PUSH IX ;DISP IX VALUE POP HL CALL OHTAB CALL PRTDBL POP AF CALL MLTSPC PUSH IY ;DISP IY VALUE POP HL CALL OHTAB CALL PRTDBL CALL CRLF JP IN ;RETURN TO INPUT MODE ; ; CHKMOD SUBROUTINE TESTS IF A BP HAS TAKEN PLACE & ; IF SO,RETURNS. IF NOT, IT RETURNS TO THE INPUT MODE. ; CHKMOD: LD A,(MODBRK) OR A RET NZ ;BP =1 POP HL ;RESTORE STACK BALANCE JP END ; ; PRMSGS SUBROUTINE OUTPUTS BP & RETURN HEADINGS & VALUES ; PRMSGS: LD HL,BRKMSG ;DISP 'BREAKPOINT:' CALL EDITOR LD HL,(ADRBRK) ;DISP BP ADDRESS CALL CHKNON ;IF BP ADDR =FFFFH, DISP 'NONE' LD HL,RETMSG ;DISP 'RETURN:' CALL EDITOR LD HL,(RETADR) ;DISP RET ADDRESS CALL CHKNON ;IF RET ADDR =FFFFH, DISP 'NONE' CALL CRLF CALL CRLF RET ; ; REGISTERS ; DATA: DB 0 ;STORAGE FOR DATA REPLACED BY BP DSPMOD: DB 0 ;0 =DISPLAY CLOSED, 1 =MEMORY DISPLAY ; ;MODE, - =REGISTER DISPLAY MODE MODBRK: DB 0 ;0 =NO BP OCCURRED, 1 =BP OCCURRED REGSET: DB 0 ;0 =MAIN SET, 1 =ALTERNATE SET ; ; MESSAGES ; BRKMSG: DB FORMF,'BREAKPOINT:',0 RETMSG: DB 8DH,'RETURN:',0 SETMSG: DB 'REG SET: ',0 ALTMSG: DB 'Alternate',CR,LF,0 MANMSG: DB 'Main',CR,LF,0 FLGMSG: DB 'FLAGS: ',0 REGMSG: DB CR,LF,'REGISTERS:',CR,LF DB 82H,'A',83H,'B',83H,'C',83H,'D',83H,'E',83H DB 'H',83H,'L',83H,'I',CR,LF,0 STKMSG: DB CR,LF,82H,'STACK PTR',82H,'X INDEX',83H,'Y INDEX',CR,LF,0 ; DTXTAB: DB 22D DB 'O' DW OPEN DB 'A' DW ASCII DB 'Z' DW ZEROC DB ASPACE DW SPCBAR DB AMINUS DW MINUS DB 'L' DW LOW1 DB 'C' DW CONTIN DB 'G' DW GO DB 'B' DW BREAK DB 'R' DW REGCOM DB 'D' DW DEPSIT DB CESC DW ESCAPE DB 'E' DW EXXCHG DB 'H' DW HEXMC DB 'Q' DW OCTMC DB 'I' DW INDATC DB 'P' DW OUTDC DB 'S' DW SERMC DB 'Y' DW YANKC DB 'W' DW WRTC DB 23H ;'#' DW SETDC DB 'F' DW LDFILC ; DS 6 ;COMMAND EXPANSION ; ; OPEN LOCATION FOR EXAMINATION COMMAND ; OPEN: EX DE,HL ;PUT DATA IN MEM POINTER JP DUMP2 ; ; LOAD ASCII CHAR IN MEMORY CMD ; ASCII: CALL CONIN ;GET CHAR ; ; LOAD LOCATION WITH 0 CMD ; ZEROC: LD E,A ;WHEN THIS ROUTINE ENTERED, A=0 LD C,WRTEN ;SET WRITE ENABLE ; ; CLOSE THIS LOCATION & OPEN NEXT LOCATION CMD ; SPCBAR: LD A,(DSPMOD) ;CHECK MODE OR A JP Z,CLEAR ;NOTHING OPENED JP M,REGSTR ;REGISTER MODE, NOT MEMORY LD HL,(LOCATN) ;FETCH OPENED LOCATION DEC C ;TEST WRITE ENABLE FLAG JR NZ,SKIPIN ;NOT ENABLED LD (HL),E ;CHANGE MEMORY SKIPIN: INC HL ;CLOSE THIS LOCATION & OPEN NEXT JP DUMP2 ;UPDATE DISPLAY & RET TO INPUT MODE ; ; CLOSE THIS LOCATION & OPEN PREVIOUS LOCATION CMD ; MINUS: LD HL,(LOCATN) DEC HL ;CLOSE THIS ONE & OPEN PREVIOUS ONE JP DUMP2 ; ; CLOSE THIS LOCATION & OPEN LOCATION SPECIFIED BY LOW ; BYTE OF DATA CMD ; LOW1: LD HL,(LOCATN) LD L,E JP DUMP2 ; ; CONTINUE FROM BP CMD ; CONTIN: CALL CHKMOD ;IN BP? LD HL,(RETADR) ;FETCH RETURN ADDRESS GO1: EX DE,HL LD HL,(USRSTK) ;BACK UP RETURN TO RST 7 LD (HL),E INC HL LD (HL),D POP AF POP BC POP DE POP HL LD SP,(USRSTK) RET ; ; EXECUTE FROM DATA CMD ; GO: EX DE,HL ;FETCH ADDR LD A,(MODBRK) ;IN BP ? OR A JR NZ,GO1 JP (HL) ; ; SET BREAKPOINT CMD ; BREAK: CALL ERSBRK ;REMOVE ANY PREVIOUS BP DEC C ;TEST & RESET WRITE ENABLE FLG JP NZ,END LD A,(DE) ;SAVE BP PGM DATA LD (DATA),A EX DE,HL ;SET BP LOCATION TO RST 48D LD (HL),RST7 LD (ADRBRK),HL ;SET BP ADDRESS POINTER LD HL,(BPVECT) ;SET BREAKPOINT RESTART VECTOR LD (HL),JMP PUSH DE INC HL LD E,(HL) LD (HL),[ENCBRK AND 0FFH] INC HL LD D,(HL) LD (HL),[ENCBRK SHR 8] LD (OLDVCT),DE POP DE JP END ; ; ERASE BREAKPOINT SUBROUTINE ; ERSBRK: LD HL,(ADRBRK) ;FETCH BP ADDRESS LD A,(DATA) ;FETCH PGM DATA LD (HL),A ;RESTORE ORIGINAL PGM DATA LD HL,NOBRK ;CLEAR BREAKPOINT ADDR LD (ADRBRK),HL PUSH HL PUSH DE LD DE,(OLDVCT) LD HL,(BPVECT) LD (HL),E INC HL LD (HL),D POP DE POP HL RET ; ; DISPLAY REGISTER CMD ; REGCOM: CALL CHKMOD ;IF NOT IN BP, IGNORE COMMAND JP REGSTR ; ; REGISTER DEPOSIT COMMAND ; DEPSIT: CALL CHKMOD ;IF NOT IN BP, IGNORE CMD LD HL,ZERO ;FETCH SP ADD HL,SP PUSH DE ;PUSH DATA EX DE,HL CALL CONIN ;INPUT DATA AND (NOT LCOFFS) LD C,RCNT ;SET TABLE COUNT LD HL,REGTAB ;SET TABLE POINTER DEPSUP: CP (HL) ;IF MATCH THEN FOUND JR Z,DEPOS2 INC HL ;POINTER +1 INC DE ;REGISTER CONTENTS POINTER +1 DEC C ;COUNT -1 JR NZ,DEPSUP CP AX JR NZ,NOTIX POP IX ;POP DATA INTO IX JP END ; NOTIX: CP AY JR NZ,NOTIY POP IY ;POP DATA INTO IY JP END ; NOTIY: POP BC ;POP DATA INTO BC CP 'I' ;IF NOT INTERRUPT REG THEN EXIT JP NZ,NOTINT LD A,C ;ELSE LOAD I REG WITH VALUE LD I,A JP END ; NOTINT: CP 'S' ;IF NOT STACK PTR THEN EXIT JP NZ,END LD (USRSTK),BC ;SET USER STACK PTR JP END ; DEPOS2: POP BC ;POP DATA INTO BC LD A,C LD (DE),A ;PUT DATA INTO REGISTER ON STACK JP END ; ; ESCAPE CMD ; ESCAPE: LD HL,(ABOVCT) JP (HL) ; ; EXCHANGE REGISTER SETS CMD ; EXXCHG: CALL CHKMOD ;IF NOT IN BP, IGNORE POP AF ;POP REGISTERS POP BC POP DE POP HL EX AF,AF' ;SWAP REGISTERS EXX PUSH HL ;PUSH NEW REGS PUSH DE PUSH BC PUSH AF LD A,(REGSET) ;INVERT REGISTER SET FLAG XOR SETMSK LD (REGSET),A JP END ; ; REGISTERS ; LOCATN: DW 0 ;OPENED MEMORY LOCATION POINTER ADRBRK: DW NOBRK ;BREAKPOINT ADDR SAVE (-1=NONE) RETADR: DW NOBRK ;BREAKPOINT RETURN ADDR SAVE OLDVCT: DW ZERO ;OLD RST7 VECTOR ADDR SAVE USRSTK: DW ZERO ;STACK POINTER SAVE UPON BREAKPOINT DS 64D ;DEBUG STACK DTXSTK: EQU $ NUMBAS: DB ZERO ;DISPLAY NUMBER BASE SAVE ; ; SET HEX MODE COMMAND ; HEXMC: LD A,ZERO LD (NUMBAS),A JP END ; ; SET OCTAL MODE COMMAND ; OCTMC: LD A,ONE LD (NUMBAS),A JP END ; ; DISPLAY INPUT PORT DATA COMMAND ; INDATC: LD C,E ;SET PORT CALL CRLF ;START NEW LINE WITH PORT # LD A,E CALL PRNUMB IN A,(C) ;GET DATA PUSH AF LD A,AEQUAL CALL CONOUT CALL SPACE POP AF CALL PRNUMB CALL CONIN CP ASPACE JR Z,INDATC JP END ; ; OUTPUT DATA TO PORT COMMAND ; OUTDC: LD C,E OUTDC1: PUSH BC CALL CRLF LD A,C ;ECHO PORT # CALL PRNUMB LD A,AEQUAL CALL CONOUT CALL SPACE CALL GETNUM LD A,B ;SAVE LAST CHAR POP BC OUT (C),E CP ASPACE ;IF LAST CHAR = SPACE THEN REPEAT JR Z,OUTDC1 JP END ; ; SEARCH MEMORY COMMAND ; SERMC: LD (TADDR),DE SERST: LD HL,BUFFER ;SET BUFFER ADDR XOR A ;SET CHAR COUNT LD (BUFCNT),A INLOOP: CALL CRLF PUSH HL CALL GETNUM POP HL LD A,B ;IF LAST CHAR NOT SPACE THEN INPUT DONE CP ASPACE JR NZ,NOTNUM LD A,E ;LOAD DATA TO BUFFER LD (HL),A INC HL LD (HL),ZERO ;SET END FLAG LD A,(BUFCNT) INC A LD (BUFCNT),A CP BUFMAX ;IF BUFFER FULL THEN ERROR JR NZ,INLOOP LD HL,BUFERR CALL EDITOR CALL CONIN ;PROMPT FOR RETRY AND 5FH ;CONVERT LC CP 'Y' JR Z,SERST JP END ; NOTNUM: LD DE,BUFFER LD HL,(TADDR) ;SET UP TO COMPARE LD BC,ZERO LD A,(DE) CPIR JP PO,NOTFND ;1ST BYTE NOT FOUND IN ENTIRE ; MEMORY LD (TADDR),HL ;SAVE NEXT LOCATION LD A,(BUFCNT) ;IF COUNT -1 =0 THEN DONE LD B,A SERLP: DEC B JR Z,DONE INC DE LD A,(DE) ;IF NEXT CHAR IN STRING NOT ; MATCHING THEN CONTINUE CP (HL) JR NZ,NOTNUM INC HL JR SERLP ; NOTFND: LD HL,NTFM CALL EDITOR CALL CONIN AND 5FH CP 'Y' JR Z,SERST JP END ; DONE: CALL CRLF LD HL,(TADDR) DEC HL CALL PRTDBL CALL CONIN CP ASPACE JR Z,NOTNUM JP END ; ; SPACE OUTPUT ROUTINE ; SPACE: PUSH AF LD A,ASPACE CALL CONOUT POP AF RET BUFFER: DS BUFMAX TADDR: DW ZERO BUFCNT: DB ZERO ; BUFERR: DB CR,LF,'TOO MANY ENTRIES, RETRY? (Y/N) ',0 NTFM: DB CR,LF,'SEQUENCE NOT FOUND, RETRY? (Y/N) ',0 ; ; LINE INPUT EDITOR ; ; ENTRY- Prompt character in D or 0 for no char ; EXIT - Char count at LINBUF, string from LINBUF+1, ; C= ESC pressed, line terminated by NUL (0) ; ;********************************************************* ; ; PARAMETERS ; CASELO: EQU 'a' ;LOWER CASE LIMIT CASEHI: EQU '{' CHAROF: EQU 20H ;OFFSET BETWEEN LCASE & UCASE ; ; ASCII CHARACTER VALUES ; CTRLX: EQU 18H ESC: EQU 1BH DEL: EQU 7FH ; ; MASKS ; CTRLMK: EQU 01100000B ;CTRL CHAR MASK ; LININ: LD HL,(INBUFP) ;GET LINE PTR LD B,ZERO ;CCOUNT=0 LD (HL),B ;SET CCOUNT INC HL ;PTR = 1ST CHAR OF STRING LD A,D ;IF NO PROMPT THEN SKIP OUTPUT OR A JR Z,CONT LD (HL),A NXTCHR: CALL CONOUT ;OUTPUT CHAR INC HL INC B ;CCOUNT +1 CALL SAVCNT LD A,B ;IF MAX LINE LENGTH THEN PRINT MSG CP MAXLIN JR Z,LNLONG CONT: CALL CONIN ;GET NEXT CHAR CP CASELO ;IF LOWER CASE THEN MAKE UPPER JR C,PCUC CP CASEHI JR NC,PCUC SUB CHAROF PCUC: CP '_' ;SWAP DELETE & UNDERSCORE JR Z,SWAP CP DEL JR NZ,NOSWAP SWAP: XOR 20H ;5FH <-> 7FH NOSWAP: CP DEL ;IF DELETE THEN GO DELETE JR Z,RUBOUT CP CTRLX ;ELSE IF CANCEL THEN GO CANCEL JR Z,CANCEL CP ESC ;ELSE IF ESCAPE THEN RETURN WITH C SCF RET Z CP CR ;ELSE IF RETURN THEN GO RETURN JR Z,CARRET LD E,A ;SAVE CHAR AND CTRLMK ;IF CTRL CHAR THEN IGNORE LD A,E JR Z,CONT LD (HL),A ;PUT CHAR IN BUFFER JR NXTCHR ; RUBOUT: INC B ;IF NO ENTRIES THEN IGNORE DEC B JR Z,CONT DEC B ;CCOUNT=CCOUNT-2 DEC B PUSH AF LD A,ASPACE ;LAST CHAR = SPACE DEC HL LD (HL),A DEC HL POP AF JR NXTCHR ; CANCEL: LD A,'$' ;OUTPUT ABORT PROMPT CALL CONOUT CALL CRLF ;NEW LINE JR LININ ; CARRET: CALL CONOUT XOR A ;SET END OF LINE FLAG LD (HL),A INC B SAVCNT: PUSH HL ;SAVE CHAR PTR LD HL,(INBUF) ;PUT CCOUNT INTO LINE LD (HL),B POP HL RET ; LNLONG: LD HL,TOOLNG ;PRINT TOO LONG MESSAGE CALL EDITOR POP HL JR LININ ; TOOLNG: DB 'LINE TOO LONG',CR,0 ; ; LINE BUFFER ; INBUFP: DW INBUF ;LINE BUFFER PTR ; INBUF: DS 82D ENDBUF: EQU $ ; MAXLIN: EQU ENDBUF-INBUF-2 ;MAX CHARS ALLOWED IN LINE ; ; ; LOAD FILES COMMAND ; LDFILC: LD (MAP),DE ;USE 1ST PARAMETER AS LOAD ADDR CALL FILSET ;SET UP TO READ CALL LOOKUP JP C,NOTFN LD BC,(MAP) ;SET READ POINTER CALL SETDMA LD HL,(EX) ;IF FILE HAS MCB THEN SKIP 1ST BLOCK LD A,'O' CP H JR NZ,NOMCB LD A,'G' CP L JR Z,MCB LD A,'A' CP L JR NZ,NOMCB MCB: LD BC,(BLOCK) INC BC CALL SETBID LD BC,(LENG) DEC BC CALL SETCNT JR RD ; NOMCB: LD BC,(BLOCK) ;ELSE READ ENTIRE FILE CALL SETBID LD BC,(LENG) CALL SETCNT RD: CALL READF JR C,SYSERR JP END ; ; MESSAGES ; FILMSG: DB CR,LF,'Filename: ',0 DRVMSG: DB CR,LF,'Drive: ',0 NTFNDM: DB CR,LF,'File not found!',0 SERRM1: DB CR,LF,'PHI-DECK ERROR: ',0 ; ; FILE PARAMETER BLOCK ; DRIVE: DB 0 NAME: DB ' ' EX: DB ' ' LENG: DW 0 ;FILE LENGTH IN BLOCKS BLOCK: DW 0 MAP: DW 0 ;MEMORY ADDRESS PTR DW 0 ;RESERVED STORAGE ; ; FILE NOT FOUND ; NOTFN: LD HL,NTFNDM CALL EDITOR CALL CONIN ;WAIT JP END ; ; SYSTEM ERROR ROUTINE ; SYSERR: PUSH AF ;SAVE ERROR CODE LD HL,SERRM1 CALL EDITOR POP AF ADD AZERO CALL CONOUT CALL CONIN JP END ; ; FILE PARAMETERS SETUP SUBR ; FILSET: LD HL,FILMSG ;OUTPUT PROMPT CALL EDITOR LD D,ZERO ;NO PROMPT CHAR CALL LININ ;INPUT FILENAME LD HL,(INBUFP) ;FORMAT FILENAME INC HL CALL DONAME LD HL,DRVMSG ;GET DRIVE # CALL EDITOR CALL GETNUM LD A,E LD (DRIVE),A CALL SETDRV CALL READIR RET ; ; FORMAT FILENAME SUBR ; DONAME: LD DE,NAME ;SET PTR PUSH DE LD A,ZERO LD B,8D ;FILL NAME BUFFER WITH NULLS DOLP: LD (DE),A INC DE DJNZ DOLP POP DE LD B,6D ;SET NAME CHAR COUNT NEXTCH: LD A,(HL) ;GET CHAR RES 7,A ;CLEAR MSBIT INC HL CALL RSVPT ;TEST FOR RESERVED CHAR JR Z,NAMEDN LD (DE),A ;SET CHAR INTO FPB INC DE DJNZ NEXTCH LD A,(HL) ;NEXT CHAR MUST BE '.' RES 7,A NAMEDN: CP APEROD JR Z,EXTNTN LD HL,NAME SET 7,(HL) RET ; EXTNTN: INC HL ;PASS OVER '.' LD B,2 LD DE,EX JR NEXTCH ; ; TEST FOR RESERVED CHAR SUBR ; RSVPT: PUSH BC ;SAVE REGS PUSH HL CP ASPACE+1 JR NC,RSVPTT CP A ;SET Z JR RSVPF ; RSVPTT: LD HL,RSVPTB ;SET PTR LD B,(HL) ;SET COUNT RSVPLP: INC HL CP (HL) JR Z,RSVPF DJNZ RSVPLP INC B ;SET NZ RSVPF: POP HL POP BC RET ; RSVPTB: DB 8D DB ASPACE,AEQUAL,AMINUS,APEROD DB COLON,SCOLON,ALT,AGT ; ; DIRECTORY HANDLING ROUTINES ; DELETE: XOR A ;SET DELETE MODE JR DIRSRH ; ENTRY: LD A,ENTMOD ;(-1) PUSH DE JR DIRSRH ; LOOKUP: LD A,ONE DIRSRH: LD (DIRMOD),A ;SET MODE LD HL,NAME ;SET FILENAME PTR LD DE,DIRBUF ;SET DIRECTORY PTR LD A,(DE) ;SET 1ST FILE BLK ID LD C,A LD B,ZERO LD (BLKTOT),BC ;SAVE FILES START INC DE ;SET ENTRY COUNT LD A,(DE) LD C,A LD A,(DIRMOD) ;IF ENTRY THEN EXIT OR A JP M,ENTRY2 NXTFIL: LD B,8D ;SET FILENAME CHAR COUNT INC DE ;IF 1ST ENTRY = DELETED THEN WASTE IT LD A,(DE) BIT 7,A JR Z,NOGOOD NXCHAR: LD A,(DE) ;DO NEXT CHAR RES 7,A ;REMOVE ATTRIBUTE BIT CP (HL) ;IF NAME <> DIR THEN WASTE IT JR Z,GOOD SET 7,A ;TRY WITH ATTRIBUTE SET CP (HL) JR NZ,NOGOOD GOOD: INC HL INC DE DJNZ NXCHAR LD A,(DIRMOD) ;IF DELETE THEN GO DELETE OR A JR Z,DELET2 INC DE ;LENGTH -> DE EX DE,HL LD E,(HL) INC HL LD D,(HL) LD (LENG),DE LD HL,(BLKTOT) ;START BLOCK -> HL PUSH HL POP BC ;START BLOCK -> SET BLOCK ID LD (BLOCK),BC CALL SETBID XOR A ;SET NC RET ; NOGOOD: INC DE ;WASTE DIRECTORY ENTRY DJNZ NOGOOD CALL ADDBLK ;ADD THIS ENTRY FILE LENGTH TO TOTAL LD A,5D ;SET ERROR CODE RET C LD HL,NAME JR NXTFIL ; DELET2: EX DE,HL ;BACK UP TO 1ST CHAR OF ENTRY LD DE,-7 ADD HL,DE INC HL ;IF WRITE PROTECT BIT SET THEN ERR BIT 7,(HL) LD A,4D ;SET WRITE PROTECT ERROR SCF RET NZ DEC HL ;ELSE DELETE ENTRY RES 7,(HL) LD BC,(BLKTOT) ;RESTORE START BLOCK LD A,ONE LD (DIRCHG),A XOR A ;SET NC RET ; ENTRY2: LD B,9D ;SET NAME CHAR COUNT PDLP: INC DE ;SKIP TO END OF DIRECTORY DJNZ PDLP DEC C ;IF AT END OF DIRECTORY THEN GO INSERT JR Z,ATLAST INC C ;ELSE ADD UP BLOCKS TOTAL & LOOP CALL ADDBLK JR ENTRY2 ; ATLAST: LD BC,(BLKTOT) ;SET BLK ID TO 1ST AVAIL. BLOCK CALL SETBID PUSH BC POP HL LD A,(DE) ;AVAILABLE BLKS -> DE LD C,A ;& BC CPL ;-AVAILABLE BLKS -> HL LD L,A INC DE LD A,(DE) LD B,A PUSH BC POP DE CPL LD H,A LD BC,(LENG) ;GET REQ'D BLKS ADD HL,BC ;IF REQ'D > AVAIL. THEN SET C LD (BLOCK),HL RET ; ; ADD FILE BLOCKS TO TOTAL SUBR ; ADDBLK: LD HL,(BLKTOT) ;GET TOTAL DEC C ;IF LAST ENTRY THEN RETURN TO ; MAIN PGM WITH C SET SCF RET Z PUSH BC ;COUNT LD A,(DE) ;ELSE ADD THIS ENTRY'S LENGTH TO TOTAL LD C,A INC DE LD A,(DE) LD B,A ADD HL,BC POP BC ;COUNT LD (BLKTOT),HL ;TOTAL BLKS RET ; ; ADD FILE TO DIRECTORY ; CLOSE: CALL DELETE ;IF ALREADY EXISTS THEN DELETE RET C ;IF WRITE PROTECTED THEN RETURN LD HL,DIRBUF ;IF ENTRIES >101D THEN RETURN INC HL LD A,(HL) CP 102D CCF RET C INC (HL) ;ENTRIES+1 LD BC,TEN ;ENTRY BYTE COUNT ADLOOP: DEC A ;COUNT JR Z,CLOSE2 ;IF PAST ALL ENTRIES THEN ADD ; NEW ONE ADD HL,BC ;ELSE SKIP OVER THIS ENTRY JR ADLOOP ; CLOSE2: INC HL ;POINT TO NEXT AVAILABLE ENTRY LD DE,NAME LD BC,8D ;MOVE COUNT EX DE,HL LDIR POP BC ;AVAIL. BLKS=AVAIL. BLKS-REQ'D BLKS LD A,B CPL LD B,A LD A,C CPL LD C,A INC BC EX DE,HL LD A,(DE) ;AVAIL. BLKS LD L,A INC DE LD A,(DE) LD H,A ADD HL,BC EX DE,HL DEC HL DEC SP DEC SP POP BC LD (HL),C INC HL LD (HL),B LD B,9D ;FILL LAST DIRECTORY ENTRY WITH NULLS EMPTY: INC HL LD (HL),ZERO DJNZ EMPTY LD (HL),E ;SET NEW AVAILABLE BLKS INC HL LD (HL),D LD A,ONE LD (DIRCHG),A RET ; ; READ DIRECTORY SUBR ; READIR: LD BC,DIRBUF ;SET READ POINTER CALL SETDMA LD BC,ZERO ;SET BLOCK ID CALL SETBID LD BC,4D ;SET BLOCK COUNT CALL SETCNT CALL REWIND JP READF ; ; WRITE DIRECTORY SUBR ; WRTDIR: LD A,(DIRCHG) ;IF NO CHANGE THEN RETURN OR A RET Z LD BC,DIRBUF ;SET WRITE POINTER CALL SETDMA LD BC,ZERO ;SET BLK ID CALL SETBID LD BC,400H ;SET BYTES TO WRITE CALL SETCNT CALL WRITF PUSH AF ;CLEAR DIRECTORY CHANGE FLG XOR A LD (DIRCHG),A POP AF RET ; DIRCHG: DB 0 DIRMOD: DB ONE BLKTOT: DW 0 ; ; YANK A BLOCK FROM TAPE COMMAND, ASSUMES DRIVE # SET ; YANKC: CALL BSETUP ;SET UP PARAMETERS CALL READF ;READ BLOCK BLKDON: JP C,SYSERR JP END ; BSETUP: PUSH DE POP BC ;SET ADDRESS CALL SETDMA LD HL,BLKMSG ;INPUT BLOCK ID CALL EDITOR CALL GETNUM PUSH DE POP BC CALL SETBID LD HL,NBLKM ;INPUT # BLKS CALL EDITOR CALL GETNUM PUSH DE POP BC CALL SETCNT RET ; BLKMSG: DB CR,LF,'Block ID = ',0 NBLKM: DB CR,LF,'Blks to read/bytes to write = ',0 ; ; SET DRIVE COMMAND ; SETDC: LD A,E CALL SETDRV JP END ; ; WRITE BYTES TO SPECIFIED BLOCK OF TAPE COMMAND ; WRTC: CALL BSETUP ;INPUT PARAMETERS CALL WRITF JR BLKDON ; IF ($ AND 0FFH) GT 0 DS 100H-($ AND 0FFH) ENDIF ; DIRBUF: DS 1024D ; END