TITLE DIAGNOSTIC DISK UTILITY LIST NOCOND ;************************************************************* ; ; Diagnostic Disk Utility ; allows xfer of data to & from a disk. ; ; Copyright 1981 GRH Electronics, CUPERTINO, CA ; ;************************************************************* ; ; Except for the CP/M version relying upon the BIOS routines, DDISK is a ; stand-alone disk access program for the JADE DD Disk controller card. It ; allows the following commands: ; FOrmat: allows formatting a new disk to JADE formats. ; DIsplay: Displays buffer data in CP/M DDT format. ; SUbstitute: Allows alteration of buffer data. ; FIll: Allows filling buffer with data ; MOve: Allows moving buffer data to new buffer location. ; LOad: Allows loading a HEX format file into buffer. (Requires CP/M) ; REad: reads specified number of sectors into memory ; WRite: writes specified sector(s) to disk. ; EXit: returns to system. ; ;************************************************************* ; revisions: ; 1.0 - Release ; ; 1.1 - Add DDT type buffer modification comands, ; Add Hex file read, limit commands to 2 chars, ; Modify source for ASMB, ; remove unused code. ; ; 1.2 - Try rel file linking again. ; ; 2.0 - Clean up for Disk version only. Removed most cond- ; itionals & superfluous source code. PS. Rel worked! ; ; 2.1 - 24 Nov 84 GRH ; Rework to remove externals. Add stand-alone capability. ; VERSION EQU '20' ; ;************************************************************ ; ; NOTE: THE FOLLOWING MODULES MUST BE LINKED TOGETHER ; WITH THIS ONE IN THIS ORDER: ; ; DDISK - MAIN MODULE (THIS MODULE) ; DDISKF - DISK I/O ROUTINES & FORMAT COMMAND ; UTIL - UTILITIES LIBRARY ; ;************************************************************ SUBTTL DECLARATIONS FALSE EQU 0 TRUE EQU NOT FALSE CPMVERS EQU TRUE INCLUD EQU FALSE ; ; MEMORY LOCATIONS ; DEFBFR EQU 0080H BDOS EQU 0005H TPA EQU 0100H ; ; DISK CONTROLLER ; WINDOW: EQU 0CC00H DFDRV: EQU 0 ;INITIAL DEFAULT DRIVE FMTSZ: EQU 100H ;FORMAT BUFFER SIZE NDRVS: EQU 2 ; ; CONSTANTS ; L1K: EQU 1024D BUFSZ: EQU 82 MAXSEC: EQU 48 SECSZ: EQU 128 ; ; ASCII CONSTANTS ; LF: EQU 0AH CR: EQU 0DH SUBTTL ASSEMBLER DIRECTIVES ; DDISKF.REL RTNS: EXTRN BSELDK, SETTRK, SETSEC, BSTDMA, RDSEC, WRSEC, FORMTC EXTRN SECTRN ; UTIL.REL RTNS: EXTRN MOVEM,FILLM,DISPM,SUBSM,READHX EXTRN DISTRT,DISEND ENTRY RDCON, CRLF, SKIPOH, GETHEX ; SYMBOLS USED BY EXTERNAL ROUTINES: ENTRY INFCB,DEFBFR,$MEMRY ENTRY NUMPARS,PARAM1,PARAM2,PARAM3,OFFSET SUBTTL MAIN PROGRAM $MEMRY: DW 0 ;LOCATION FOR FREE MEMORY PTR ;------------------------------------------------ ; ; THIS IS THE ENTRY POINT FROM THE SYSTEM: ; ;------------------------------------------------ DDISK: LD (SYSSTK),SP ;SAVE STACK LD SP,STACK LD HL,SGNONM ;OUTPUT SIGN-ON MESSAGE CALL EDITOR LD HL,($MEMRY) ;MAKE RAM START ON EVEN NIBBLE LD A,L AND 0FH ;IF ALREADY THERE THEN OK AS IS JR Z,PTROK LD A,L ;MOD 16 AND 0F0H ADD 10H ;BUMP FOR > 0 LD L,A LD A,0 ADC A,H LD H,A LD ($MEMRY),HL PTROK: LD (DISTRT),HL ;INIT BUFFER DISPLAY PTRS LD (DISEND),HL LD (DBUFRP),HL ;INIT R/W BUFFER PTR MAINLP: LD BC,INBUFR ;SET UP FOR COMMAND LD (CMDPTR),BC LD A,BUFSZ LD (BC),A PUSH BC ;OUTPUT PROMPT LD C,'*' CALL CO POP BC CALL RDCON LD HL,INBUFR+1 ;PUT NUL AT END OF LINE LD A,(HL) INC HL ;PTR = 1ST CHAR OF CMD PUSH HL ;SAVE FOR LATER ADD A,L LD L,A LD A,0 ADC A,H LD H,A LD (HL),0 POP HL ;CMD PTR CALL SKIPOH ;IGNORE SPACES JR Z,CMDERR ;OOPS - NO COMMAND EX DE,HL LD (CMDPTR),DE LD HL,CMDTBL ;SET UP FOR COMMAND TABLE SEARCH LD C,(HL) ;GET ENTRY COUNT NXTCMD: INC HL LD B,(HL) CMDLP: INC HL LD A,(DE) ;IF COMMAND <> TABLE THEN MOVE ON CP (HL) JR NZ,NOMAT INC DE DJNZ CMDLP INC HL ;FOUND, GET EXECUTION ADDR LD E,(HL) INC HL LD D,(HL) EX DE,HL LD DE,CMDRET ;SET UP RETURN ADDR PUSH DE LD C,' ' ;SET COMMAND PTR TO NEXT OPERAND PUSH HL ;SAVE COMMAND ENTRY LD HL,(CMDPTR) CALL SERCHH LD (CMDPTR),HL POP HL ;EXECUTE COMMAND JP (HL) CMDRET: PUSH AF ;TERMINATE LINE CALL CRLF POP AF JP NC,MAINLP JP CMDERR NOMAT: INC HL ;WASTE TABLE ENTRY DJNZ NOMAT INC HL DEC C ;IF NOT LAST THEN LOOP LD DE,(CMDPTR) JR NZ,NXTCMD ;---------------------------- ; ; INVALID COMMAND- ERROR ; ;---------------------------- CMDERR: LD HL,INVCM ;OUTPUT INVALID COMMAND MESSAGE CALL EDITOR JP MAINLP ;############################ ; ; SIGN ON MESSAGE ; ;############################ SGNONM: DB CR,LF,' Diagnostic Disk Utility Ver ' DB HIGH VERSION DB '.' DB LOW VERSION DB CR,LF,' (c) 1981 GRH Electronics',CR,LF OPTMSG: DB CR,LF,'OPTIONS:' DB CR,LF,' Prints this list' DB CR,LF,'FOrmat a disk' DB CR,LF,'REad :drive @trk >sec #cnt *addr %(translate)' DB CR,LF,'WRite :drv @trk >sec #cnt *addr %' DB CR,LF,'LOad addr filename.HEX' DB CR,LF,'MOve first, last, dest' DB CR,LF,'FIll first, last, data' DB CR,LF,'DIsplay <,last>' DB CR,LF,'SUbstitute addr' DM CR,LF,'EXit return to system',CR,LF,LF INVCM: DM CR,LF,LF,'Invalid command! - Re-enter.',CR,LF,LF ;############################ ; ; COMMAND TABLE ; ;############################ CMDTBL: DB ENTCNT DB 2,'MO' ;MOVE DW MOVEC DB 2,'FI' ;FILL DW FILLC DB 2,'DI' ;DISPLAY DW DISPC DB 2,'SU' ;SUBSTITUTE DW SUBSC DB 2,'LO' ;LOAD HEX DW LOADHXC DB 2,'RE' ;READ DW READC DB 2,'WR' ;WRITE DW WRITEC DB 2,'FO' ;FORMAT DW FORMTC DB 2,'EX' ;EXIT DW EXITC DB 2,'HE' ;HELP DW HELPC DB 1,'?' ;SAME AS HELP DW HELPC ENTCNT: EQU 11 SUBTTL COMMANDS ;**************************** ; ; EXIT COMMAND ; ;**************************** EXITC: LD SP,(SYSSTK) ;RESTORE STACK JP 0 ;**************************** ; ; HELP COMMAND ; ;**************************** HELPC: LD HL,OPTMSG CALL EDITOR OR A RET DATA SYSSTK: DW 0 CMDPTR: DW INBUFR INBUFR: DB BUFSZ ;CONSOLE READ BUFFER LENGTH DB 0 ;CONSOLE CHARS READ DS BUFSZ REL ;**************************** ; ; READ SECTOR COMMAND ; ;**************************** READC: XOR A ;CLEAR WRITE FLAG JR DACCES ;**************************** ; ; WRITE SECTOR COMMAND ; ;**************************** WRITEC: LD A,TRUE ;SET WRITE COMMAND DACCES: LD (WRFLG),A CALL DSETUP ; ; THE FOLLOWING WAS IMPLEMENTED TO ALLOW REPEATED ACCESSES ; LD A,(DSEC) ;MOVE PARAMETERS TO LOCAL VARS LD (CSEC),A LD HL,(DBUFRP) LD (CBUFRP),HL LD HL,(DSCNT) LD (CSCNT),HL DKLP: LD A,(DTRAN) ;IF TRANSLATE FLAG = TRUE THEN TRANSLATE OR A LD A,(CSEC) LD C,A LD B,0 JR Z,TRNOT CP 27 ;IF ATTEMPTING TO TRANSLATE > 26 SECTORS THEN JR NC,TRNOT ;NO TRANSLATION DEC C ;EXPECTS {0..N-1} LD DE,SDTRAN ;SET TRANSLATION TABLE PTR CALL SECTRN LD C,L TRNOT: CALL SETSEC LD BC,(CBUFRP) CALL BSTDMA LD A,(WRFLG) OR A JR NZ,WRT CALL RDSEC JR OPDONE WRT: CALL WRSEC OPDONE: BIT 7,A ;IF ERROR THEN EXIT JR Z,OPOK PUSH AF LD HL,DSKERM ;OUTPUT MESSAGE CALL EDITOR POP AF LD L,A ;OUTPUT ERROR CODE CALL PUTHEX CALL CRLF OR A ;RETURN CLEAN RET OPOK: LD HL,(CBUFRP) ;PTR := PTR + SECTOR SIZE LD DE,SECSZ ADD HL,DE LD (CBUFRP),HL LD HL,CSEC INC (HL) INC HL ;IF COUNT = 0 THEN DONE DEC (HL) JR NZ,DKLP RET DSKERM: DM CR,LF,LF,'Disk Error - Returned Code= ' ;############################ ; ; DISK ACCESS TABLE ; ;############################ DATA DDRIVE: DB 0 ;DISK DRIVE DTRK: DB 1 ;TRACK # ; *** THESE TWO MUST BE IN THIS ORDER TO WORK *** DSEC: DB 1 ;SECTOR # DSCNT: DW 1 ;SECTOR COUNT DBUFRP: DW 0 ;DISK DATA BUFFER PTR CBUFRP: DW 0 CSEC DB 1 CSCNT DW 1 WRFLG: DB FALSE ;DISK WRITE FLAG DTRAN: DB FALSE ;SECTOR TRANSLATION FLAG REL ;************************************** ; ; DISK PARAMETER FETCH SUBR ; ;************************************** DSETUP: LD HL,(CMDPTR) LD C,':' ;FETCH DRIVE # CALL SERCHH LD A,(DDRIVE) ;DEFAULT DRIVE = CURRENT DRIVE JR Z,DRVOK INC HL CALL SKIPOH PUSH HL POP BC CALL GETDEC LD A,L DRVOK: LD (DDRIVE),A LD C,A LD E,0 ;LOGON VECTOR := FULL LOGON CALL BSELDK LD HL,(CMDPTR) LD C,'@' ;FETCH TRACK # CALL SERCHH LD A,(DTRK) ;DEFAULT = CURRENT_TRACK JR Z,TRKOK INC HL CALL SKIPOH PUSH HL POP BC CALL GETDEC LD A,L TRKOK: LD (DTRK),A LD C,A CALL SETTRK LD HL,(CMDPTR) ;FETCH SECTOR # LD C,'>' CALL SERCHH LD A,(DSEC) ;DEFAULT = CURRENT_SECTOR JR Z,SECOK1 INC HL CALL SKIPOH PUSH HL POP BC CALL GETDEC LD A,L SECOK1: LD (DSEC),A LD C,A CALL SETSEC LD HL,(CMDPTR) LD C,'#' CALL SERCHH LD DE,1 JR Z,CNTOK INC HL CALL SKIPOH PUSH HL POP BC CALL GETDEC EX DE,HL CNTOK: LD (DSCNT),DE LD HL,(CMDPTR) ;FETCH BUFFER PTR LD C,'*' CALL SERCHH LD DE,(DBUFRP) JR Z,BFROK INC HL ;FETCH OFFSET CALL SKIPOH PUSH HL POP BC CALL GETHEX LD DE,($MEMRY) ;ADD IN OFFSET ADD HL,DE EX DE,HL BFROK: LD (DBUFRP),DE LD HL,(CMDPTR) ;SET TRANSLATION FLAG LD C,'%' CALL SERCHH RET Z ;IF NOT SPEC'D THEN USE LAST INC HL CALL SKIPOH LD A,(HL) SUB '0' ;0: FALSE, /0: TRUE NOTRN: LD (DTRAN),A RET SUBTTL MOVE MEMORY COMMAND ;**************************** ; ; MOVE COMAND ; ;**************************** MOVEC: CALL GETPARMS ;GET PARAMS JP C,DATAERR ;IF NO OPERANDS THEN RETURN CP 3 JP C,DATAERR LD HL,(PARAM1) ;ADD OFFSET TO PARAMS CALL ADDOFF JP C,BNDSERR LD (PARAM1),HL LD HL,(PARAM2) CALL ADDOFF JP C,BNDSERR LD (PARAM2),HL LD HL,(PARAM3) CALL ADDOFF JP C,BNDSERR LD (PARAM3),HL CALL MOVEM ;GOTO EXTERNAL SUBR JP C,BNDSERR RET SUBTTL FILL MEMORY COMMAND ;**************************** ; ; FILL COMAND ; ;**************************** FILLC: CALL GETPARMS JP C,DATAERR ;IF PARM CNT < 3 THEN ERR CP 3 JP C,DATAERR LD HL,(PARAM1) CALL ADDOFF JP C,BNDSERR LD (PARAM1),HL LD HL,(PARAM2) CALL ADDOFF JP C,BNDSERR LD (PARAM2),HL CALL FILLM ;GOTO EXT SUBR JP C,BNDSERR RET SUBTTL DISPLAY MEMORY COMMAND ;********************************************************** ; ; DISPLAY MEMORY COMMAND - TRICKY ; ENTRY- IF PARAM1 = -1 THEN OLD PARAM2 IS USED FOR PARAM1 ; IF PARAM2 = 0 THEN 16 LINES ARE OUTPUT ; ;********************************************************** DISPC: CALL GETPARMS CP 3 ;IF PARM CNT > 2 THEN ERR JP NC,DATAERR LD C,A LD HL,(PARAM1) ;IF P1 <> -1 THEN INC HL LD A,L OR H DEC HL JR Z,DISP1 CALL ADDOFF ;P1 = P1 + OFFSET JR DISP2 DISP1: LD HL,(DISEND) ;ELSE P1 = LAST END DISP2: LD (PARAM1),HL LD HL,(PARAM2) ;IF P2 <> 0 THEN LD A,L OR H JR Z,DISP3 CALL ADDOFF ;P2 = P2 + OFFSET JR DISP4 DISP3: LD DE,16*16 ;ELSE P2 = P1 + 16 LINES LD HL,(PARAM1) ADD HL,DE DISP4: LD (PARAM2),HL CALL DISPM ;EXTERNAL SUBR OR A RET SUBTTL SUBSTITUTE MEMORY COMMAND ;************************************** ; ; SUBSTITUTE MEMORY COMMAND ; ;************************************** SUBSC: CALL GETPARMS JP C,DATAERR CP 2 ;IF COUNT > 1 THEN ERR JP NC,DATAERR LD HL,(PARAM1) CALL ADDOFF JP C,BNDSERR LD (PARAM1),HL JP SUBSM ;EXTERNAL SUBR SUBTTL LOAD HEX FILE COMMAND ;**************************** ; ; LOAD HEX FILE COMAND ; ;**************************** LOADHXC: LD HL,(CMDPTR) CALL SKIPOH ;IF NO OPERAND THEN ERR JP Z,DATAERR LD (CMDPTR),HL ;P1 = VALUE 1 PUSH HL POP BC CALL GETHEX LD (PARAM1),HL LD HL,(CMDPTR) ;GET FILENAME LD C,' ' CALL SERCHH JP Z,DATAERR LD (CMDPTR),HL LD HL,(PARAM1) ;ADD OFFSET CALL ADDOFF JP C,BNDSERR LD (PARAM1),HL LD HL,(CMDPTR) LD DE,INFCB CALL FCBFMT LD A,0 ;FUDGE UNTIL NEW FCBFMT PROM BURNED LD (INRECD),A LD HL,INTYPE ;MAKE HEX FILE LD (HL),'H' INC HL LD (HL),'E' INC HL LD (HL),'X' LD BC,INFCB CALL OPEN INC A JR NZ,LOAD1 LD HL,FNFMSG CALL EDITOR OR A RET LOAD1: LD BC,(PARAM1) LD DE,(BDOS+1) CALL READHX ;EXTERNAL SUBR OR A ;IF NO ERRORS THEN RETURN RET Z AND 3 DEC A ;COMPUTE OFFSET SLA A LD HL,ERRMTBL ADD A,L LD L,A LD A,0 ADC A,H LD H,A LD A,(HL) INC HL LD H,(HL) LD L,A CALL EDITOR OR A RET ;###################################### ; ; HEX FILE ERROR MESSAGES ; ;###################################### ERRMTBL: DW HXFILER DW HXCONVE DW BNDSM FNFMSG: DM CR,LF,'File Not Found!',CR,LF HXFILER: DM CR,LF,'Hex File Error',CR,LF HXCONVE: DM CR,LF,'Hex Conversion Error',CR,LF BNDSM: DM CR,LF,'Command Value out of Bounds!',CR,LF DATAM: DM CR,LF,'Not Enough Data!',CR,LF ;************************************** ; ; DATA ERROR MSG OUTPUT SUBR ; ;************************************** DATAERR: LD HL,DATAM CALL EDITOR OR A RET ;************************************** ; ; BOUNDS ERROR MSG OUTPUT SUBR ; ;************************************** BNDSERR: LD HL,BNDSM CALL EDITOR OR A RET ;###################################### ; ; 3740 FORMAT PARAMETERS ; **** CP/M SINGLE DENSITY **** ; ;###################################### SDTRAN: DB 1,7,13,19,25,5,11,17,23,3,9,15,21 DB 2,8,14,20,26,6,12,18,24,4,10,16,22 SUBTTL SUBROUTINES ;********************************************************** ; ; GET PARAMETERS SUBR ; ENTRY- (CMDPTR) = POINTER TO 1ST PARAM OR SPACE BEFORE ; EXIT - NUMPARS = ACTUAL PARAMETER COUNT (0-3) ACCEPTED ; A = NUMPARS ; PARAM1-3 = PARAMETER VALUES ; PARAM1 = -1 IF LEADING ',' ENCOUNTERED ; PARAM2-3 = 0 IF NO PARAMS GIVEN ; ;********************************************************** GETPARMS: LD HL,0 ;INIT VALUES LD (NUMPARS),HL LD (PARAM2),HL LD (PARAM3),HL DEC HL ;P1 = -1 LD (PARAM1),HL LD HL,(CMDPTR) ;SKIP LEADING SPACES CALL SKIPOH SCF RET Z LD (CMDPTR),HL LD A,(HL) ;IF CHAR = ',' THEN SKIP TO 2ND CP ',' JR Z,GETP2 PUSH HL POP BC CALL GETHEX LD (PARAM1),HL ;SAVE P1 LD HL,NUMPARS INC (HL) GETP2: LD HL,(CMDPTR) ;GET NEXT PARAM LD C,',' CALL SERCHH RET Z INC HL ;PASS ',' CALL SKIPOH RET Z LD (CMDPTR),HL ;SAVE PTR PUSH HL POP BC CALL GETHEX LD (PARAM2),HL LD HL,NUMPARS ;CNT = CNT + 1 INC (HL) GETP3: LD HL,(CMDPTR) LD C,',' CALL SERCHH RET Z INC HL CALL SKIPOH RET Z LD (CMDPTR),HL PUSH HL POP BC CALL GETHEX LD (PARAM3),HL LD A,(NUMPARS) ;CNT = CNT + 1 INC A LD (NUMPARS),A RET ;************************************** ; ; ADD OFFSET SUBR ; ENTRY- HL= VALUE TO BE OFFSET ; EXIT - HL= NEW VALUE ; DE= MODIFIED ; CF= OVERFLOW ; ;************************************** ADDOFF: LD DE,(OFFSET) ADD HL,DE RET ;OVERFLOW ERROR SUBTTL ASCII RTNS ;************************************************ ; ; SEARCH FOR CHAR SUBR ; ENTRY- C= CHAR TO SEARCH FOR ; HL= TEXT PTR (0 TERMINATED) ; EXIT - HL= PTR TO FOUND CHAR ; DE= HL ON ENTRY ; ZF= NOT FOUND ; ;************************************************ SERCHH: LD A,(HL) ;IF CHAR == 0 THEN RETURN 0 OR A RET Z CP C ;IF CHAR == *PTR THEN BREAK JR Z,SERCHFND INC HL ;NEXT CHAR JR SERCHH SERCHFND: OR A ;RETURN NZ RET ;************************************************ ; ; SKIP CHARS UNTIL NEXT FIELD SUBR ; ENTRY- HL= TEXT PTR (0 TERMINATED) ; EXIT - HL= 1ST NON-SPACE CHAR PTR ; ZF= END OF LINE ; ;************************************************ SKIPOH: LD A,(HL) ;IF *PTR != ' ' THEN RETURN NZ CP ' ' JR NZ,SKIPFND INC HL JR SKIPOH SKIPFND: OR A ;RETURN NZ RET ;************************************** ; ; CRLF OUTPUT SUBR ; ;************************************** CRLFM: DM CR,LF CRLF: LD HL,CRLFM ;OUTPUT STRING ;************************************************ ; ; TEXT OUTPUT SUBR ; ENTRY- HL= TEXT PTR (>80H TERMINATED) ; ;************************************************ EDITOR: LD E,(HL) ;GET CHAR & 7FH RES 7,E PUSH HL ;OUTPUT IT LD C,2 CALL BDOS POP HL BIT 7,(HL) ;IF CHAR > 80H THEN RETURN RET NZ INC HL ;ELSE NEXT CHAR JR EDITOR SUBTTL CONVERSION RTNS ;************************************************ ; ; ASCII -> HEX CONVERSION ; ENTRY- BC= TEXT PTR (0 TERMINATED) ; EXIT - HL= NUMBER ; CF= INVALID NUMBER ; ;************************************************ GETHEX: LD HL,0 ;TOTAL = 0 GETHLP: LD A,(BC) ;GET CHAR OR A ;IF CHAR == 0 THEN RETURN RET Z SUB '0' ;CONVERT ASCII TO BINARY RET C ;IF CHAR < 0 THEN RETURN ERR CP 10 ;IF CHAR > 9 && CHAR < 'A' THEN RETURN ERR JR C,GETHOK SUB 7 CP 10 RET C CP 16 CCF RET C GETHOK: ADD HL,HL ;SHIFT TOTAL OVER ADD HL,HL ADD HL,HL ADD HL,HL ADD L ;ADD NEW TO TOTAL LD L,A INC BC ;NEXT CHAR JR GETHLP ;************************************************ ; ; ASCII -> DECIMAL CONVERSION SUBR ; ENTRY- BC= TEXT PTR (0 TERMINATED) ; EXIT - HL= NUMBER ; CF= INVALID NUMBER ; DE= ? ; ;************************************************ GETDEC: LD HL,0 ;TOTAL = 0 GETDLP: LD A,(BC) ;GET CHAR OR A ;IF CHAR == 0 THEN RETURN NC RET Z SUB '0' ;CONVERT ASCII TO BINARY RET C ;IF NOT NUMERIC THEN RETURN CF CP 10 CCF RET C PUSH HL ;TOTAL POP DE ADD HL,HL ;TOTAL = TOTAL * ((4 + 1) * 2) ADD HL,HL ADD HL,DE ADD HL,HL ADD A,L ;ADD NEW TO TOTAL LD L,A LD A,0 ADC A,H LD H,A INC BC JR GETDLP ;********************************* ; ; OUTPUT HEX NUMBER SUBR ; ENTRY- HL= # TO OUTPUT ; ;********************************* ENTRY PUT2HX, PUTHEX PUT2HX: LD A,H CALL PTHEX PUTHEX: LD A,L PTHEX: OR A ;CLEAR CY RLA CALL PRDIG PRDIG: RLA ;OUTPUT MS DIGIT RLA RLA RLA PUSH AF ;SAVE PUSH HL AND 0FH ;MASK CP 10 ;IF NUMERIC THEN OK AS IS JR C,NTALPH ADD 7 ;ELSE CONVERT 10..15 -> A..F NTALPH: ADD '0' ;CONVERT TO ASCII LD C,A CALL CHOUT POP HL POP AF RET SUBTTL CPM RTNS ;********************************* ; ; CONSOLE INPUT FUNCTION ; EXIT - A= CHAR ; ;********************************* CI: LD C,1 JP BDOS ;**************************** ; ; CONSOLE OUTPUT SUBR ; ENTRY- C= CHAR ; ;**************************** ENTRY CO, CHOUT CHOUT: CO: LD E,C LD C,2 JP BDOS ;************************************** ; ; READ CONSOLE BUFFER FUNCTION ; ENTRY- BC= BUFFER PTR ; ;************************************** RDCON: PUSH BC POP DE LD C,10 JP BDOS ;********************************* ; ; CONSOLE STATUS FUNCTION ; EXIT - A= 0: NOT READY ; ;********************************* ENTRY CSTS CSTS: LD C,11 JP BDOS ;**************************** ; ; OPEN FILE FUNCTION ; ENTRY- BC= FCB PTR ; ;**************************** OPEN: PUSH BC POP DE LD C,15 JP BDOS ;**************************** ; ; READ SEQUENTIAL FUNC ; ENTRY- BC= FCB PTR ; EXIT - A= 0: OK ; ;**************************** ENTRY RDSEQ RDSEQ: PUSH BC POP DE LD C,20 JP BDOS ;**************************** ; ; SET DMA FUNCTION ; ENTRY- BC= XFER ADDR ; ;**************************** ENTRY SETDMA SETDMA: PUSH BC POP DE LD C,26 JP BDOS SUBTTL FCB FORMATTER SUBR ;************************************************************* ; ; CP/M FILE CONTROL BLOCK FORMATTER ; ENTRY- HL= POINTER TO ASCII STRING OF FILENAME ; DE= POINTER TO FCB TO FORMAT ; EXIT - HL= POINTER TO TERMINATION CHAR OF STRING ; ('/' OR ANY CHAR LESS THAN 21H) ; DE= FCB PTR ; ZF= NO WILDCARDS USED ; NZ= WILDCARD(S) USED (A= # OF WILDCARDS) ; ;************************************************************* DFLTDK: EQU 0004H ;DEFAULT DISK LOCATION ZROSIZ: EQU 21 ;NUMBER OF BYTES TO INIT NAMCNT: EQU 8 ;FILENAME CHAR CNT TYPCNT: EQU 3 ;FILE EXTENSION CHAR CNT FCBFMT: PUSH DE ;SAVE FCB PTR FOR RETURN EX DE,HL SKIP: LD A,(DE) ;SKIP LEADING SPACES CP '/' JR Z,L89 CP ' ' JR C,L89 JR NZ,FCB1 INC DE JR SKIP FCB1: SUB '@' ;MAKE 'A'-'P' = 1-15 FOR DRIVE # LD B,A INC DE ;IF NEXT CHAR = ':' THEN MUST BE DRIVE LD A,(DE) CP ':' JR Z,L90 DEC DE ;ELSE BACK UP & USE DEFAULT DRIVE L89: LD A,(DFLTDK) LD (HL),A ;FCB(DISK) := DRIVE # JR L96 L90: LD A,B ;USE SPECIFIED DISK LD (HL),B INC DE ;SKIP OVER ':' L96: LD B,NAMCNT ;B := MAX CHARS L98: CALL RSVP JR Z,LB9 INC HL ;PTR := PTR +1 CP '*' ;IF WILDCARD THEN ENTER '?' JR NZ,LA9 LD (HL),'?' JR LAB LA9: LD (HL),A ;ADD CHAR TO FCB FILENAME INC DE LAB: DJNZ L98 ;IF NOT DONE THEN LOOP LAF: CALL RSVP ;IF RESERVED CHAR THEN EXIT JR Z,LC0 INC DE ;SKIP OVER EXTRA CHARS TO '.' JR LAF LB9: INC HL ;FILL REMAINDER OF FCB WITH SPACES LD (HL),' ' DJNZ LB9 LC0: LD B,TYPCNT ;COUNT = SIZEOF(TYPE) CP '.' ;IF CHAR != '.' THEN FILL WITH SPACES JR NZ,LE9 INC DE ;GET NEXT CHAR AFTER '.' LC8: CALL RSVP ;IF RESERVED CHAR THEN EXIT JR Z,LE9 INC HL ;IF CHAR <> '*' THEN EXIT CP '*' JR NZ,LD9 LD (HL),'?' JR LDB LD9: LD (HL),A ;ADD CHAR TO FCB INC DE LDB: DJNZ LC8 LDF: CALL RSVP ;IF RESERVED CHAR THEN EXIT JR Z,LF0 INC DE ;WASTE CHARS JR LDF LE9: INC HL ;FILL REMAINING TYPE WITH SPACES LD (HL),' ' DJNZ LE9 LF0: LD B,ZROSIZ ;ZERO EXTENT, S1, S2, RECORD COUNT LF2: INC HL LD (HL),0 DJNZ LF2 POP HL ;COUNT WILDCARDS PUSH HL LD BC,NAMCNT+TYPCNT L01: INC HL LD A,(HL) CP '?' JR NZ,L09 INC B L09: DEC C JR NZ,L01 LD A,B OR A POP HL ;SET UP REGS FOR RETURN EX DE,HL RET ;************************************** ; ; RESERVED CHAR TEST SUBR ; ENTRY- (DE) = CHAR TO TEST ; EXIT - ZF = FOUND ; ;************************************** RSVP: LD A,(DE) ;IF CHAR <= ' ' THEN RETURN Z CP ' ' + 1 JR NC,RSVP1 XOR A RET RSVP1: PUSH BC PUSH HL LD B,TABCNT ;B := ENTRY COUNT LD HL,RSVPT RSVPL: CP (HL) JR Z,RSVPX ;IF FOUND THEN EXIT INC HL DJNZ RSVPL INC B ;RETURN NZ RSVPX: POP HL POP BC RET RSVPT: DB '=_.:;,<>/' ;RESERVED CHAR TABLE TABCNT: EQU $-RSVPT DATA NUMPARS DB 0 ;NUMBER OF PARAMETERS ENTERED PARAM1 DW 0 ;1ST PARAM ENTERED PARAM2 DW 0 ;2ND PARAM ENTERED PARAM3 DW 0 ;3RD PARAM ENTERED OFFSET EQU $MEMRY ;POINTER TO DATA BUFFER INFCB: DS 9 INTYPE: DS 3 DS INFCB + 36 - $ INRECD EQU INFCB + 32 DS 128 STACK: EQU $ END DDISK